闭包是函数携带定义时的完整词法环境引用链,而非值拷贝;它持有所见外部变量的实时引用,支持独立副本、持续更新与内存驻留。

函数作为返回值时携带的完整闭包环境,本质是它“打包带走”了定义时所能看到的所有外部变量和它们当时的绑定关系——不是拷贝值,而是持有一个活的引用链。
闭包环境不是快照,而是实时引用
当内部函数被返回,它并没有把外部变量的值复制一份,而是保留在自己的[[Environment]]内部槽中,持续指向外层作用域的词法环境记录(Lexical Environment Record)。这意味着:
- 外部变量后续被修改,闭包内仍能读到最新值(比如 count++ 每次都累加)
- 多个闭包实例可各自维护独立的外层变量副本(如多次调用 createCounter(),每个 counter 都有自己专属的 count)
- 只要闭包还存在,这些变量就不会被垃圾回收,哪怕外层函数早已执行完毕
这个环境包含哪些内容
所谓“完整”,指的是内部函数在定义时所能访问到的整个词法作用域链,包括:
- 直接外层函数的参数和局部变量(如 x、count)
- 更外层函数(如果有)的变量(支持多层嵌套闭包)
- 全局作用域中的变量和函数(但通常不视为“闭包捕获”的重点)
- 注意:不包含 this、arguments 或 new.target 等动态绑定值,它们由调用时决定
怎么验证闭包环境真实存在
可以用 Chrome DevTools 的“Scope”面板直观查看:在断点处暂停,展开 Closure 项,就能看到所有被捕获的变量名及其当前值。也可以通过调试器观察变量是否随闭包调用而持续更新,比如:
立即学习“Java免费学习笔记(深入)”;
function makeMultiplier(m) { return function(n) { return m * n; }; }const double = makeMultiplier(2);
const triple = makeMultiplier(3);
console.log(double(5), triple(5)); // 10 和 15 —— m 在各自闭包中保持独立
容易误解的点
常见误区包括:
- 认为闭包“保存的是值” → 实际保存的是对变量的引用
- 以为只有 return 才形成闭包 → 其实只要内部函数被赋值、传参或作为事件处理器等脱离原作用域使用,就已构成闭包
- 混淆作用域链与执行上下文 → 闭包绑定的是定义时的词法环境,不是调用时的执行上下文
不复杂但容易忽略


















