-
this 在 javascript 的指向规则总结为:
- 在调用函数时使用new关键字,函数内的this是一个全新的对象。
- 如果apply、call或bind方法用于调用或创建一个函数,函数内的 this 就是作为参数传入这些方法的对象。
- 当函数作为对象里的方法被调用时,函数内的this是调用该函数的对象。比如当obj.method()被调用时,函数内的 this 将绑定到obj对象。
- 如果调用函数不符合上述规则,那么this的值指向全局对象(global object)。浏览器环境下this的值指向window对象,但是在严格模式下 (‘use strict’),this的值为undefined。
如果符合上述多个规则,则较高的规则(1 最高,4 最低)将决定this的值; 如果该函数是 ES2015 中的箭头函数,将忽略上面的所有规则,this被设置为它被创建时的上下文。
-
要弄明白 this 指向的原理,就要先理解执行环境(执行上下文)。执行环境有三种:
- 全局级别的代码 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境。
- 函数级别的代码 - 当执行一个函数时,运行函数体中的代码。
- Eval的代码 - 在Eval函数内运行的代码。
javascript是一个单线程语言,这意味着在浏览器中同时只能做一件事情。当javascript解释器初始执行代码,它首先默认进入全局上下文。每次调用一个函数将会创建一个新的执行上下文。每次新创建的一个执行上下文会被添加到作用域链的顶部,有时也称为执行或调用栈。浏览器总是运行位于作用域链顶部的当前执行上下文。一旦完成,当前执行上下文将从栈顶被移除并且将控制权归还给之前的执行上下文。不同执行上下文之间的变量命名冲突通过攀爬作用域链解决,从局部直到全局。这意味着具有相同名称的局部变量在作用域链中有更高的优先级。 简单的说,每次你试图访问函数执行上下文中的变量时,查找进程总是从自己的变量对象开始。如果在自己的变量对象中没发现要查找的变量,继续搜索作用域链。它将攀爬作用域链检查每一个执行上下文的变量对象,寻找和变量名称匹配的值。
-
执行上下文的建立过程。
我们现在已经知道,每当调用一个函数时,一个新的执行上下文就会被创建出来。然而,在javascript引擎内部,这个上下文的创建过程具体分为两个阶段:
- 建立阶段(发生在当调用一个函数时,但是在执行函数体内的具体代码以前):
- 建立变量,函数,arguments对象,参数。
- 建立作用域链。
- 确定this的值。
- 代码执行阶段:
变量赋值,函数引用,执行其它代码。
-
建立阶段以及代码执行阶段的详细分析:
确切地说,执行上下文对象(上述的executionContextObj)是在函数被调用时,但是在函数体被真正执行以前所创建的。函数被调用时,就是我 上述所描述的两个阶段中的第一个阶段 - 建立阶段。这个时刻,引擎会检查函数中的参数,声明的变量以及内部函数,然后基于这些信息建立执行上下文对象 (executionContextObj)。在这个阶段,variableObject对象,作用域链,以及this所指向的对象都会被确定。
上述第一个阶段的具体过程如下:
- 找到当前上下文中的调用函数的代码。
- 在执行被调用的函数体中的代码以前,开始创建执行上下文:
进入第一个阶段-建立阶段:
- 建立variableObject对象:
- 建立arguments对象,检查当前上下文中的参数,建立该对象下的属性以及属性值
- 检查当前上下文中的函数声明:
- 每找到一个函数声明,就在variableObject下面用函数名建立一个属性,属性值就是指向该函数在内存中的地址的一个引用。
- 如果上述函数名已经存在于variableObject下,那么对应的属性值会被新的引用所覆盖。
- 检查当前上下文中的变量声明:
- 每找到一个变量的声明,就在variableObject下,用变量名建立一个属性,属性值为undefined。
- 如果该变量名已经存在于variableObject属性中,直接跳过(防止指向函数的属性的值被变量属性覆盖为undefined),原属性 值不会被修改。
- 初始化作用域链
- 确定上下文中this的指向对象
- 代码执行阶段:
执行函数体中的代码,一行一行地运行代码,给variableObject中的变量属性赋值。
可以看出 this 是 上下文执行环境中的一个属性,依据调用栈和执行位置决定的(或者说执行环境),并且 this 是在运行时绑定的,并不是在编写时绑定。this指向什么完全取决于函数在哪里被调用。
两篇对 this 指向的举例说明:
[来自 SevenBig ] (https://blog.csdn.net/itSeven7/article/details/81260899)
[来自 这波能反杀 ] (https://www.jianshu.com/p/a6d37c77e8db)