在 for 循环中正确隔离变量应使用 let 声明,因其每次迭代创建独立绑定,避免闭包捕获错误值;var 会共享变量导致终值问题;const 不适用于计数型循环;老环境可用 IIFE 封装;数组遍历时推荐 let 或 for...of + const。

在 for 循环中正确隔离变量,关键在于让每次迭代拥有独立的变量绑定,而不是共享同一个变量。现代 JavaScript 中,用 let 声明循环变量是最直接、最可靠的方式。它天然利用块级作用域机制,在每次迭代时创建新的绑定,避免闭包捕获错误值的问题。
let 声明自动创建每次迭代的独立绑定
for 循环体(花括号内)是一个块级作用域,而 let i 在每次迭代开始时都会生成一个全新的绑定,不是复用同一内存地址。这意味着每个 setTimeout、事件回调或函数闭包引用的 i,都是该轮次独有的值。
- 写法示例:
for (let i = 0; i < 5; i++) { setTimeout(() => console.log(i), 100); } - 输出结果:0、1、2、3、4(顺序可能略有浮动,但数值准确)
- 对比 var:var 声明的 i 属于函数作用域,所有回调最终都读取循环结束后的终值(如 5)
不要误用 const 或重复声明
const 不适合直接用于计数型循环变量,因为它的值不可重新赋值,会导致 i++ 报错。另外,避免在回调里写 let i = i 这类语句——这会新建一个同名局部变量,无法解决外部捕获问题,反而造成混淆。
- 错误写法:
for (const i = 0; i < 5; i++) { ... }(语法报错) - 无效写法:
setTimeout(() => { let i = i; console.log(i); }, 100)(i 未定义,形成暂时性死区)
需要兼容老环境时用 IIFE 封装
如果项目需支持 ES5 或旧版浏览器(如 IE),可用立即执行函数表达式(IIFE)手动构造独立作用域,把当前 i 的值作为参数传入:
立即学习“Java免费学习笔记(深入)”;
- 写法示例:
for (var i = 0; i < 5; i++) { (function(j) { setTimeout(() => console.log(j), 100); })(i); } - 原理:形参 j 在每次调用时获得 i 的快照值,各次调用的作用域互不干扰
- 注意:箭头函数本身不提供新作用域,关键仍是外部变量的声明方式
扩展:对数组/对象项也适用相同逻辑
当循环处理数组或对象时,同样建议用 let 解构或显式声明局部变量,确保异步操作拿到的是当轮数据,而非循环末尾的引用:
for (let i = 0; i < arr.length; i++) { let item = arr[i]; fetch(`/api/${item.id}`).then(...); }- 或更清晰地:
for (const item of arr) { fetch(`/api/${item.id}`).then(...); }(for...of 本身配合 const 即可保证每次 item 独立)


















