JavaScript new创建构造函数实例时箭头函数this指向差异原因
二者this指向差异的根本原因
首先要明确一个核心规则,所有箭头函数的this逻辑都建立在这个规则之上:
箭头函数自身不持有
this绑定,它的this是定义时就被永久确定的,取值为定义位置外层最近一层非箭头函数作用域的this,和后续的调用方式、挂载对象、call/apply/bind手动绑定、new操作都没有关系,一旦确定永远不会变。
接下来结合new调用构造函数的执行流程,分别看两个箭头函数的定义场景:
1. 构造函数执行时的上下文绑定规则
当代码执行new Foo()时,JS引擎会按固定流程初始化实例:
- 第一步创建一个全新的空对象
- 第二步将空对象的原型关联到
Foo.prototype - 第三步将构造函数
Foo内部的执行上下文this,强制绑定到刚创建的这个空对象上 - 第四步逐行执行
Foo内部的代码 - 最后如果构造函数没有显式返回对象类型的值,就把这个新对象作为
new的返回值,也就是代码里的foo变量。
2. logContext1的this来源
logContext1是在Foo构造函数内部逐行执行代码的阶段定义的:
function Foo() { // 这行代码执行时,构造函数内的this已经被new绑定到新创建的foo实例 this.logContext1 = () => console.log('logContext1', this); }
这个箭头函数定义时,外层作用域就是构造函数Foo的函数作用域,外层的this已经被new绑定为foo实例,所以箭头函数永久捕获的this就是foo实例,后续不管怎么调用,这个指向都不会变。
3. logContext2的this来源
logContext2的定义时机是在new Foo()执行完全结束、构造函数调用栈弹出之后,代码运行到全局作用域时才定义的:
let foo = new Foo(); // 这行代码运行在全局作用域下 foo.logContext2 = () => console.log('logContext2', this);
这个箭头函数定义时,外层作用域是全局作用域,非严格模式下全局作用域的this指向window(严格模式下为undefined),所以它永久捕获的this就是window。哪怕它被挂载为foo对象的属性,通过foo.xxx()的形式调用,也不会改变它的this——对象调用方法时this指向对象的规则只对普通函数生效,箭头函数完全不遵循这个调用时绑定的逻辑。
内容的提问来源于stack exchange,提问作者Akshay
相关产品推荐
相关产品推荐

