Promise构造函数内局部变量如何维持状态?
关于Promise构造函数局部变量状态维持与闭包的疑问解答
首先纠正一个对闭包的误解:闭包不是只有「外部函数返回内部函数」这一种形式。闭包的核心是内部函数能访问外部函数作用域里的变量,哪怕外部函数已经执行完毕——不管这个内部函数是被返回出去,还是挂载到对象上,或是被传递给其他函数,只要它还存在,就会形成闭包。
拿Promise的简易实现来说,看这段核心代码:
function MyPromise(executor) { // 构造函数内的局部变量,用来存状态和值 let state = 'pending'; let value = null; const callbacks = []; // 内部定义的resolve函数,闭包了state、value、callbacks function resolve(val) { if (state !== 'pending') return; state = 'fulfilled'; value = val; callbacks.forEach(cb => cb.onFulfilled(val)); } // 内部定义的reject函数,同样闭包了局部变量 function reject(reason) { if (state !== 'pending') return; state = 'rejected'; value = reason; callbacks.forEach(cb => cb.onRejected(reason)); } // 挂载到实例上的then方法,也闭包了state、value、callbacks this.then = function(onFulfilled, onRejected) { return new MyPromise((resolveNext, rejectNext) => { if (state === 'fulfilled') { // 直接使用构造函数里的value const res = onFulfilled(value); resolveNext(res); } else if (state === 'rejected') { // 直接使用构造函数里的value(reason) const res = onRejected(value); resolveNext(res); } else { // 往构造函数里的callbacks数组加回调 callbacks.push({ onFulfilled: (val) => { const res = onFulfilled(val); resolveNext(res); }, onRejected: (reason) => { const res = onRejected(reason); resolveNext(res); } }); } }); }; executor(resolve, reject); }
当你创建const promiseA = new MyPromise(...)时,MyPromise构造函数会完整执行一次:
- 此时创建了
state、value、callbacks这几个局部变量; - 定义了
resolve、reject函数,以及挂载到this(也就是promiseA实例)上的then方法; - 把
resolve和reject传给executor函数执行。
构造函数执行完毕后,这些局部变量并没有被销毁——因为resolve、reject、promiseA.then这三个函数都引用了它们,形成了闭包。
比如:
- 当executor里调用
resolve(xxx)时,执行的是构造函数里定义的那个resolve,它修改的是当初构造函数执行时创建的state和value; - 当你调用
promiseA.then(...)时,执行的是挂载到实例上的then方法,它直接读取的是当初构造函数里的state和value,或者往callbacks数组里加回调——这些变量都是第一次构造函数执行时创建的,不会重新生成。
所以哪怕每次调用then都会创建新的Promise实例,原Promise实例的状态变量依然会被闭包保留,不会被回收,自然能维持住状态。
内容的提问来源于stack exchange,提问作者lch
相关产品推荐
相关产品推荐

