闭包是函数与其定义时词法作用域绑定形成的结构,本质为定义时生成的作用域快照;需满足嵌套定义、真实引用外部局部变量、作用域链固化等条件,其生命周期由引用关系维持,实现“定义时决定、运行时延续”。

闭包的本质,是函数与其定义时所处的词法作用域绑定形成的结构。它不是运行时“创建”的对象,而是函数在定义那一刻就自然携带的作用域快照。
作用域嵌套是闭包产生的前提
只有当一个函数在另一个函数内部定义,并且内部函数实际引用了外部函数的局部变量(而非全局变量或参数),才满足闭包的结构基础。这种嵌套关系在代码解析阶段就已固定,与后续是否调用无关。
- 嵌套层级决定作用域链长度:每多一层嵌套,内部函数的作用域链就多一级外层环境
- 变量必须被“真实使用”:仅声明不引用不算;像
return () => x中的x被读取,才算捕获 - ES6 的
let/const块级作用域也参与闭包:内部函数可捕获for (let i...)中的每次迭代绑定
生命周期由引用关系动态延续
外部函数执行完毕后,其局部执行上下文本该销毁,但只要内部函数仍存在引用(比如被赋值给全局变量、作为回调传入异步操作),JS 引擎就会保留该上下文中被闭包捕获的变量。
- 变量不会“随父函数消亡”:它们的内存存活期取决于闭包函数是否还被持有
- 闭包函数本身不释放 → 捕获的变量不释放 → 可能引发内存泄漏(如事件监听器未解绑)
- 垃圾回收判断依据是“是否可达”:从全局根出发,能否通过闭包函数访问到那些变量
词法作用域决定了“看到谁”,而闭包让“看到”变成“一直拥有”
词法作用域规定了函数能访问哪些变量——这是静态规则;闭包则把这一静态能力固化为运行时的持久引用。二者共同构成“定义时决定、运行时延续”的完整逻辑链条。
- 作用域链是查找路径,闭包是这条路径上被长期持有的某一段环境
- 没有作用域嵌套,就没有闭包;没有闭包机制,作用域链就只是查找工具,无法延长变量生命
- Python 中可通过
func.__closure__查看被捕获变量;JavaScript 中可在 DevTools 的 Scope 面板观察 Closure 环境











