闭包的本质是内部函数“记住”并持续访问其定义时所在外部作用域的能力,它由词法作用域链支撑,需同时满足嵌套结构、引用外层变量、内层函数被带出外层作用域三个条件,使外部变量在函数执行完毕后仍因引用而保留在内存中。

闭包的本质,是内部函数“记住”并持续访问其定义时所在外部作用域的能力。它不是语法糖,也不是特殊指令,而是 JavaScript(以及 Python、Go 等语言)作用域规则自然运行的结果。
闭包形成的三个必要条件
只有同时满足以下三点,才构成真正意义上的闭包:
- 存在嵌套结构:一个函数(内层)被定义在另一个函数(外层)内部
- 内层函数引用了外层函数的局部变量(非全局、非参数传入)
- 该内层函数以某种方式被“带出”外层作用域——最常见的是作为返回值,或被赋值给外部变量、传给其他函数
为什么内部函数能访问外部变量?靠的是词法作用域链
函数在定义时就确定了它能访问哪些变量,这个范围由代码书写位置决定,叫“词法作用域”。当内层函数执行时,引擎会按作用域链逐级向上查找:先找自身作用域,再找外层函数作用域,再找全局。闭包让这条链在外部函数执行完毕后依然有效。
例如:
function makeAdder(x) {
return function(y) { return x + y; };
}
const add5 = makeAdder(5);
add5(3); // 输出 8
这里的 x 是 makeAdder 的参数,本应在函数退出后销毁,但因为内部函数记住了它,所以一直保留在内存中。
闭包让作用域“活”了下来
普通函数执行完,它的局部变量通常会被垃圾回收。闭包打破了这一常规——只要内部函数还存在且可能被调用,它所依赖的外部变量就不会被释放。
- 这不是“复制”,而是持有引用;修改变量会影响所有共享该闭包的调用
- 多个闭包可共享同一外层作用域(如多个计数器共用同一个 count)
- 每个闭包实例拥有自己独立的外层变量副本(如 makeAdder(5) 和 makeAdder(10) 各自保存不同的 x)
常见误区提醒
仅定义在函数内部 ≠ 闭包;必须有变量引用 + 外部存活才算。
- 函数返回一个普通值(如数字、字符串),不形成闭包
- 内部函数没引用外层变量,即使返回也不算闭包
- 立即执行的内层函数(如 function() { ... }())若未被外部保留,一般也不构成实用闭包











