for循环中闭包保存变量状态的核心是固化每次迭代的变量值,常用方法有:①IIFE传参捕获当前i;②ES6+用let声明实现块级作用域;③数组用forEach天然隔离参数;④bind预设参数。

在 for 循环中使用闭包保存变量状态,核心是让每次迭代的变量“固化”在函数作用域内,避免因变量提升或共享引用导致所有回调都访问到循环结束后的最终值。最常见场景是为多个元素绑定事件或设置定时器时,期望每个回调拿到对应轮次的 i 值。
用立即执行函数(IIFE)捕获当前 i 值
ES5 时代常用方式:把当前的 i 作为参数传入一个立即执行的匿名函数,在其内部形成独立作用域。
for (var i = 0; i < 3; i++) {
(function(index) {
setTimeout(() => console.log(index), 100);
})(i);
}
// 输出:0, 1, 2
说明:每次迭代调用 IIFE,index 是该轮次的副本,不会随外部 i 变化而改变。
用 let 声明替代 var(推荐,ES6+)
let 具有块级作用域,每次 for 迭代都会创建一个新的绑定,天然解决闭包问题。
立即学习“Java免费学习笔记(深入)”;
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出:0, 1, 2
注意:必须用 let(不能是 var),且不能在循环体外再访问 i —— 它只在本轮块内有效。
用 forEach 或其他数组方法替代 for
若遍历的是数组,可直接用 forEach,它的回调函数本身就是一个闭包,参数自动隔离:
[0, 1, 2].forEach((item, index) => {
setTimeout(() => console.log(index), 100);
});
// 输出:0, 1, 2
优势:语义清晰、无变量声明污染、天然避免闭包陷阱;缺点:不适用于纯数字计数或非数组结构。
用 bind 显式绑定参数(较少用,但可行)
将当前 i 作为预设参数绑定到函数上:
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 100);
}
// 输出:0, 1, 2
说明:bind 返回的新函数会把第一个参数固定为当时的 i 值,适合简单场景,但可读性略低。
本质上,闭包保存状态的关键不是“写闭包”,而是确保函数能访问到它定义时那一时刻的变量值。现代代码优先选 let + for,简洁安全;兼容老环境则用 IIFE;操作数组时优先用 forEach 或 map 等高阶函数。


















