电话
400 9058 355
闭包是JavaScript中内部函数访问外部变量并逃逸执行时自动形成的运行时行为;需同时满足函数嵌套、变量捕获、逃逸执行三条件;用于封装私有状态、解决循环索引问题,但可能引发内存泄漏。
闭包 是 JavaScript 中函数“记住自己出生地”的能力:当一个函数被定义在另一个函数内部,并且**访问了外部函数的变量**,同时这个内部函数**被返回或传到别处执行**,它就形成了闭包。
它不是语法糖,也不是设计模式,而是一种运行时行为——只要满足这三个条件,闭包就自动产生。
闭包不是写出来的,是“跑出来”的。判断一个函数是不是闭包,只看三点:
inner 函数体里直接用了 outer 的局部变量(比如 let count、const config)inner 被返回、赋值给变量、传给 setTimeout 或事件监听器,**脱离了原始调用环境**缺一不可。比如下面这个就不是闭包:
function outer() {
const x = 1;
function inner() {
console.log('I ignore x'); // 没引用外部变量
}
return inner;
}
inner 虽然嵌套,但没捕获任何自由变量,引擎不会为它保留作用域链。
JavaScript 没有 #private 字段(ES2025+ 才有,且不兼容旧环境),而闭包是长期稳定、全版本兼容的私有变量方案。
典型写法:
function createCounter() {
let count = 0; // 外部变量 → 被闭包保护
return {
increment() { count++; },
getCount() { return count; }
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 1
这里 count 对外完全不可见,连 counter.count 都是 undefined。所有修改必须走暴露的方法。
var 了这是新手踩坑最多的地方。下面这段代码会输出 5 个 5:
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100);
}
因为 var 是函数作用域,i 全局共享;所有回调共用同一个 i,等真正执行时循环早已结束,i === 5。
用闭包修复(ES5 方式):
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(() => console.log(j), 100);
})(i);
}
更现

for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100);
}
let 声明每次迭代都创建新绑定,本质就是语言层帮你做了闭包封装——你不用手动写 IIFE,但原理一样。
闭包让变量“活”得更久——只要内部函数还存在,它引用的所有外部变量就无法被垃圾回收。
Closure 类型,看哪些变量被意外滞留闭包本身不是问题,问题在于“该释放时不释放”。它像一把没有保险栓的刀——好用,但得清楚自己握着哪一头。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...