Promise构造函数中箭头函数this为何关联实例对象?
原始代码示例
function Promise (callback){ //this = {} //because of "new" keyword, an empty object is automatically created, and the "this" is referencing to that object. this.status = "pending"; const resolve = () => { this.status = "fulfilled"; console.log("status is: " + this.status) }; callback(resolve); //return this // at the end, javascript automatically returns the "this" object. } console.log("start") const p1 = new Promise((resolve) => { setTimeout(() => resolve(), 3000); }); setTimeout(() => console.log(p1.status), 4000) //output: //start //status is: fulfilled //fulfilled
疑问描述
当前p1是Promise的实例对象,构造函数返回this给p1后,resolve函数3秒后才执行。resolve并非实例属性或原型方法(未定义为this.resolve或Promise.prototype.resolve),但执行时却修改了p1的status。
我的疑问是:将resolve传入callback时,resolve内部的this指向的是构造时创建的空对象this = {}而非p1吗?但实际执行resolve时它能修改p1的状态,说明this指向p1,这是为什么?
即使修改为如下代码:
this.resolve = () => { this.status = "fulfilled"; console.log("status is: " + this.status) }; callback(this.resolve);
我理解其中的this仍指向构造时创建的空对象this = {},这也让我困惑。
解答
核心原因:箭头函数的this是词法绑定的
- 用
new调用构造函数时,内部的this就是正在创建的实例对象(也就是最终的p1),所谓的this = {}只是创建过程的简化描述,这个空对象最终就是p1,二者是同一个引用,并非两个不同的对象。 - 箭头函数没有独立的
this,它的this是定义时所在作用域的this,和调用方式无关。
针对第一个代码场景
在Promise构造函数里定义const resolve = () => {...}时,箭头函数的作用域就是构造函数的执行上下文,此时构造函数内的this就是正在创建的p1实例。箭头函数会捕获这个this并固定下来,所以不管3秒后以什么方式调用resolve,它内部的this始终指向p1,自然能修改p1.status。
针对修改后的代码场景
把resolve挂载到this上(即p1.resolve),但它依然是箭头函数,this还是词法绑定到构造函数执行时的this(也就是p1)。哪怕将this.resolve传递出去调用,内部的this也不会改变,依然指向p1,所以同样能修改实例的状态。
总结:构造函数中的this从一开始就指向最终的实例p1(只是创建过程中逐步添加属性),箭头函数定义时捕获了这个this,后续无论何时调用,都能通过这个this操作p1的属性。
内容的提问来源于stack exchange,提问作者JethroT

