let 声明循环变量可为每次迭代创建独立绑定,避免闭包取值错误;var 因函数作用域和变量提升导致所有回调共享同一变量实例,输出全为循环终值。

用 let 声明循环变量,就能在每次迭代中创建独立绑定,避免闭包中取值错误——这是块级作用域最典型的实战价值。
为什么 var 在循环里会“共享”变量
var 声明的变量具有函数作用域(或全局作用域),且存在变量提升。在 for 循环中,整个循环共用一个变量实例:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出:3, 3, 3
因为所有回调都引用同一个 i,循环结束时 i 已变为 3,所以全部打印 3。
let 如何实现每次迭代的变量隔离
let 声明具有块级作用域,且在每次 for 迭代开始时,都会为该次迭代创建一个新的绑定(不是简单复制值,而是新绑定):
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出:0, 1, 2
这背后是 ES6 规范定义的“词法绑定初始化”机制:每次迭代都生成独立的 i 绑定,每个回调捕获的是各自迭代对应的绑定。
- 不依赖闭包“保存值”的技巧(如立即执行函数)
- 无需手动创建作用域,语法简洁直观
- 适用于
for、for...of、for...in等所有标准循环
注意边界情况:解构与复合声明
let 的块级绑定对常见写法有效,但需留意以下情形:
- 在
for中解构赋值(如for (let [k, v] of map))同样享受每次迭代独立绑定 - 若在循环体内用
let重新声明同名变量(如let i = 5),会报错:重复声明 -
const不能用于计数器循环(因不可重新赋值),但可用于遍历只读结构(如for (const item of arr))
兼容性与替代方案(仅当需支持旧环境时)
现代浏览器和 Node.js(v6+)均原生支持 let 块级绑定。若必须兼容 IE 或极老运行时:
- 用立即执行函数包裹(IIFE):
(function(i) { setTimeout(() => console.log(i), 100); })(i); - 用
Array.prototype.forEach:[0,1,2].forEach(i => setTimeout(() => console.log(i), 100)); - 避免在循环中直接使用
var+ 异步操作,这是最易出错的组合

















