我们在前面说过,在执行上下文创建过程中做了三件事:创建变量对象,生成作用域链,确定this指向。今天我们就来探讨一下this指向的问题。首先先回顾一下我们执行上下文的生命周期图:
执行上下文是函数被调用时创建的,创建过程包括确定this指向,所以this的指向是在函数被调用时确定的。
我们知道,this对象是在运行时基于函数的执行环境绑定的:在全局环境中,this指向window,当函数被作为某个对象的方法调用时,this指向那个对象。不过实际情况中往往没有那么好判断,今天我们就来梳理一下。
全局对象中的this
在全局环境下,this永远指向window。
函数中的this
this指向调用这个函数的对象。
由于函数test是被全局对象(window)调用的,因此函数内部的this指向window。
由于函数fn是被对象obj调用的,因此函数fn内部的this指向对象obj。
另外,由于obj不是个函数,不适合上面的规则,我们要单独讨论,如果obj对象在全局创建,那么obj里面的this指向window。
构造函数
构造函数和其他函数的唯一区别,就是他们的调用方式不同。任何函数,只要通过new
操作符来调用,那它就可以作为构造函数,调用时经历以下四个步骤:
- 创建一个新对象;
- 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
- 执行构造函数中的代码(为这个新对象添加属性);
- 返回新对象。
|
|
创建新对象new Test()
后,this指向这个新对象,然后为这个新对象添加属性a = 1
,再执行console.log(this.a)
,此时输出的就是刚添加的a值。返回这个新对象传递给了实例对象fun
,此时this指向了实例fun
,因此fun.a
也为1。
函数用call或apply调用
我们可以利用call或apply手动设置this的指向,这两个方法的第一个参数都是this将要指向的对象,后面的参数,都是向将要执行的函数传递参数。其中call以一个一个的形式传递,apply以数组的形式传递,这是他们唯一的不同。
这个例子很容易理解,本来调用test函数this指向全局对象,是无法访问到obj对象中的num的,但是利用call和apply方法将this指向了obj对象,所以可以顺利输出。
以上就是我目前知道的关于this指向的几种情况,以后可能会再补充。