深入理解JavaScript系列(5):this
在《深入理解 JavaScript 系列(2):执行上下文栈》中提到,当 JavaScript 代码执行代码时,就会创建一个执行上下文。
对于执行上下文,都有三个重要属性:
- 变量对象 (Variable Object - VO)
- 作用域链
- this
我们来介绍一下 this。
this
什么是 this 呢?我们可以把 this 的指向当作执行时所指向的执行上下文。在不同的上下文中,this 的确定经常会发生问题。
this 是执行上下文中的一个属性。
1 | globalContext = { |
VO 就是上一节讲到的变量对象了。
this 与上下文中可执行代码的类型有直接关系,this 值在进入上下文时确定,并且在上下文运行期间永久不变
全局代码中的 this
全局代码中的 this 始终是全局对象本身。
1 | this.a = 1; |
那么全局对象本身是什么呢?在浏览器中就是我们经常使用的 window
。
1 | console.log(this); // window 对象 |
函数中的 this
函数中的 this 是很奇特的,也是很有趣的。它的指向并不是固定的,而且可以通过手动进行修改。
我们在上面介绍到,this 是进入上下文时确定,所以在一个函数代码中,这个值在每一次完全不同。
注意:任何时候不能改变 this 的值。
1 | let objBind = { value: 2 }; |
我们看到结果的结果是不同的。
发现,指向的结果是不是跟调用它的对象有关呢?事实就是这样,谁调用就指向谁。
我们使用 obj
来调用 test
方法时,指向了 obj
,打印 true
,而我们将方法赋给 objBind
之后,objBind
来调用时,指向了 objBind
。
我们来看一下执行 test
方法时,test
上下文:
1 | // obj 调用执行 |
通过上下文,我们可以清楚的了解到 this
在运行中的指向。
我们来看一下还有一种方式,指向了全局对象。
1 | let test = obj.test; |
这时候执行 test 时的上下文:
1 | testContext = { |
作为构造函数下的 this
1 | function Constructor() { |
函数调用时,手动设置 this
在这里就要使用到 Function.prototype.apply
或 Function.prototype.call
了。
在这里也介绍了 apply
和 call
以及 bind
,可以看我的这两篇文章 - 《深入理解 JavaScript 系列(8): call/apply 函数》 与 《深入理解 JavaScript 系列(9): bind 函数》
1 | let obj = { |
多言一句 - 箭头函数指向
箭头函数的 this
指向,不能按照上面的任何一种来。
箭头函数的 this
指向,是在定义时决定的,而不是在调用时决定。
1 | var value = 1; |