ES5中var无块级作用域,需用IIFE创建独立作用域并利用闭包捕获当前值:单次逻辑用(function(){...})();,循环中则传参如(function(i){...})(i)固定每次迭代值。

在 ES5 环境中,var 声明的变量只有函数作用域,没有块级作用域(比如 if 或 for 内部无法真正隔离变量)。要实现类似 let 的效果,核心思路是:**用函数创建独立作用域,并通过闭包捕获当前迭代值或局部状态**。
用 IIFE 封装单次块逻辑
立即执行函数表达式(IIFE)是最直接的方式。它定义一个匿名函数并立刻调用,形成一个私有作用域,内部 var 变量对外不可见。
例如:
(function () {
var temp = 'inside';
console.log(temp); // 正常输出
})();
console.log(temp); // ReferenceError: temp is not defined
这种写法适合一次性执行、不需要复用的代码块,比如初始化配置、防污染的临时计算等。
在循环中固定每次迭代的变量值
ES5 循环配合异步操作(如 setTimeout、事件监听)时,var i 会被所有回调共享,最终全部输出循环结束后的值(如 5)。解决方法是把当前索引作为参数传入 IIFE,让闭包“记住”那一刻的值。
典型写法:
var arr = ['a', 'b', 'c'];
for (var i = 0; i (function (index) {
setTimeout(function () {
console.log(arr[index]); // 每次输出对应元素
}, 100 * index);
})(i);
}
- 外层
for中的i是全局可变的,但每次调用 IIFE 时,index参数接收了当时的i值 - 内部回调函数形成闭包,持续引用这个
index,不受后续i变化影响 - 也可解构为
(function (item) { ... })(arr[i]),直接捕获值而非索引
封装成可复用的“伪 let”工具函数
若项目中多处需要模拟块级绑定,可抽象一个辅助函数,提升可读性:
function blockScope(fn, ...args) {
return fn.apply(null, args);
}
// 使用:
for (var i = 0; i blockScope(function (j) {
console.log('第', j, '次');
}, i);
}
本质仍是 IIFE + 参数传递,但语义更清晰,也方便后期统一替换为 let。
注意闭包带来的内存潜在影响
闭包会维持对外部变量的引用,若不当使用(比如在长生命周期对象中保留大量大数组或 DOM 引用),可能延迟垃圾回收。
建议:
- 只在必要时创建闭包,避免无意义嵌套
- 及时解除事件监听或清空引用(尤其在单页应用中反复绑定时)
- 避免在循环中创建复杂闭包体(如内含大型对象或定时器)

















