闭包在手写 promise 源码中的核心作用是捕获并持久化 promise 实例的内部状态和回调队列,确保异步回调能准确访问创建时的上下文,实现状态隔离、链式调用和异步调度的正确性。

闭包在手写 Promise 源码中,核心作用是**捕获并持久化 Promise 实例的内部状态(pending/fulfilled/rejected)和待执行的回调队列(onFulfilledQueue/onRejectedQueue)**,让异步操作完成后的 resolve/reject 调用能准确找到对应 Promise 的上下文,触发正确的回调执行。
闭包封装 Promise 内部状态与队列
每个 Promise 实例都应拥有独立的状态和回调队列。若用全局变量或 this 属性但不加保护,多个 Promise 会互相干扰;而通过构造函数中的局部变量 + 方法闭包,可天然隔离:
- 在 Promise 构造函数内声明 status、value、reason、onFulfilledQueue、onRejectedQueue 等局部变量
- 所有原型方法(如 then、resolve、reject)通过闭包访问这些变量,无需依赖 this 或外部作用域
- 即使异步任务延后执行(如 setTimeout、Promise.resolve().then),回调函数仍能通过闭包引用到创建时的那组变量
then 方法返回新 Promise 并维护各自闭包
then 必须返回新 Promise,且新 Promise 的状态由上一个 Promise 的回调执行结果决定。此时需两层闭包协作:
- 外层闭包:保存当前 Promise 的 status/value/reason 和回调队列(供 resolve/reject 触发时使用)
- 内层闭包:在 then 中为新 Promise 创建独立的状态变量,并将 onFulfilled/onRejected 处理逻辑包裹进函数,推入原 Promise 的对应队列
- 当原 Promise 状态变更,遍历队列执行每个处理函数时,它们通过闭包持有各自 new Promise 的 resolve 和 reject 函数,从而控制新 Promise 的状态流转
异步调度中闭包确保回调“认得清主人”
Promise/A+ 规范要求 then 回调必须异步执行(microtask)。即使 Promise 已同步 settled,then 注册的回调也要等当前栈清空后才执行。这时闭包的关键作用是:
- 回调函数被推入 microtask 队列(如 queueMicrotask)时,已绑定好对当前 Promise 状态和新 Promise 控制函数的引用
- 后续 microtask 执行该回调时,不依赖任何运行时 this 或参数传递,直接从闭包取值,避免状态错乱或 this 指向丢失
- 例如:queueMicrotask(() => { if (status === 'fulfilled') { onFulfilled(value) }) —— 这个箭头函数闭包住了定义时的 status 和 value
避免常见闭包陷阱:不要在循环中直接 push 未绑定上下文的函数
手写时容易在批量处理回调队列时出错,比如:
- ❌ 错误写法:for (let i = 0; i fn()) } —— 所有回调共享同一个 i 和 fn 闭包,可能执行错序或取值错误
- ✅ 正确做法:用立即执行函数或 for...of 遍历,或用箭头函数在每次迭代中捕获当前项,确保每个 microtask 闭包独立绑定自己的 onFulfilled/onRejected 和对应 Promise 上下文
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











