中阶魔法 - this 指向(一)

前情提要

艾草:「this is a book。」

「你在做什麽呀?」

艾草:「练习你的语言呀。」
(艾草设定为鸟类。)

「很棒,继续加油!」

艾草:「啊念到 this ,想到还没教你一个魔法的核心观念!今天来学 this 吧!」


this 指向(一)

在执行环境与执行堆叠文章,有提到过创造阶段 JavaScript 会去建立 this ,那 this 是什麽呢?

先复习一下:

  • 执行环境分为:全域执行环境、函式执行环境
  • 执行环境建立时分为:创造阶段、执行阶段
  • 执行环境创造阶段会建立 this

接下来,把 this 印出来看看!

console.log(this);
function test() {
  console.log(this);
}
test();

印出结果:

https://ithelp.ithome.com.tw/upload/images/20211011/20139066bSKQ1ue988.png

会发现它们都指向 Window 物件,到这边可能会以为 this 指向都固定都是指向全域执行环境建立的全域物件,接着看底下的例子:

let obj = {
    name: '艾草',
    mana: 1100,
    test: function () {
        console.log(this);
    }
};
obj.test();

印出结果:

https://ithelp.ithome.com.tw/upload/images/20211011/20139066istLaQLIf9.png

会发现它指向了 obj

这是为何呢?this 的指向跟它所处的执行环境无关,而跟如何呼叫它有关系,而范例程序码的指向如图:

https://ithelp.ithome.com.tw/upload/images/20211011/201390669HQMtFDWv2.png

请特别留意呼叫该函式时前方的物件为何,this 就会指向该物件。


接下来,来介绍几种常见情境!

全域环境 this 指向

在全域环境下调用 this 的指向皆会指向全域物件。

console.log(this === window);//true

简易呼叫 Simple Call

只要是简易呼叫的方式,this 都会指向全域物件,简易呼叫就是直接呼叫该函式,像上方一开始的范例:

var name = '全域艾草';
function sayHello() {
	let name = '艾草';
  console.log(`Hello , ${this.name}`);//Hello , 全域艾草
}
sayHello();

物件方法

物件方法内调用的函式会指向呼叫它的物件本身,也是上方范例有提到的部分,因为很重要,所以再来复习一次:

var name = '全域艾草';
let obj = {
    name: '艾草',
    sayHello: function () {
        console.log(`Hello , ${this.name}`);//Hello , 艾草
    }
};
obj.sayHello();

https://ithelp.ithome.com.tw/upload/images/20211011/20139066eGezRDTbbO.png

DOM 事件处理器

在监听函式内调用 this 时,会发现 this 会指向触发事件的元素本身:

HTML

<button type="button">按钮</button>

JavaScript

let button = document.querySelector('button');
button.addEventListener('click', function (e) {
    console.log(this);
});

印出结果:

https://ithelp.ithome.com.tw/upload/images/20211011/20139066vlFa3ADzXQ.png

总结

  • 全域环境下调用 this 会指向全域物件
  • 简易呼叫下调用的 this 会指向全域物件
  • 物件方法调用的 this 会指向调用它的物件
  • 监听函式内调用的 this 会指向触发事件的元素

小练习

请问以下 this 的指向叙述何者错误?

//选项一
//全域情况下
console.log(this);

//选项二
let num = 1;
let obj = {
  num: 2,
  add: function () {
    console.log(this.num + this.num);
  }
};
obj.add();

//选项三
var num = 1;
function add() {
  let num = 2;
  console.log(this.num + this.num);
}
add();

A 选项一会指向全域物件 Window
B 选项二会印出 4
C 选项三会印出 4

解答: C 错误,选项三印出结果为 2 ,选项三为简易呼叫,简易呼叫下 this 会指向全域


参考文献

JavaScript 全攻略:克服 JS 的奇怪部分(Udemy)
Vue 3 实战影音课程(六角学院)
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/this


<<:  Day 27 用户拒绝权定义规划实作

>>:  [Day 26] Android Studio 七日陨石开发:嘘! 我正在监听这个元件

第十八天:用 Plugin 扩充 TeamCity

昨天提到 TeamCity 支援几个不同的通知频道,可以在建置任务成功或失败的时候通知我们。不过现在...

【Day07】记忆体存放与释放

在 Day04 有提到在 JavaScript 里, 函式执行时会产生函式执行环境,在该执行环境中会...

学习JavaScript第三天--使用vscode写出js--console.log印出资讯

VScode: Step 1 开启index.html存挡 Step 2 开启all.js存挡 St...

【把玩Azure DevOps】Day10 CI/CD从这里:第2个Pipeline,建立共用的Build Pipeline

从前面的几篇文章应该已经知道建立新的Pipeline可以从哪里开始,所以废话不多说,第二个Pipel...

Oracle 1Z0-082 Practice Exam 2021

**Actual Oracle 1Z0-082 Practice Exam - Easiest Wa...