let在每次循环迭代时创建新绑定,使变量隔离,避免闭包问题;var则因函数作用域共享同一变量导致异步回调获取最终值。

在 JavaScript 中,let 关键字通过块级作用域(block scope)让循环内部的变量真正“每次迭代独立”,解决了 var 声明带来的经典闭包问题。
为什么 for 循环里用 let 能避免变量污染?
let 在每次循环迭代时,都会为变量创建一个**新的绑定(binding)**,而不是复用同一个变量。这意味着每个迭代中的变量是隔离的,尤其在异步或回调中表现明显。
- var 声明的变量提升到函数作用域顶层,整个循环共用一个 i,所有回调看到的都是循环结束后的最终值(如 i === 5)
- let 声明的变量绑定在每次 { } 迭代块中,每个 setTimeout 拿到的是各自迭代时刻的 i 值
常见写法:for 和 for...of 中 let 的行为
以下两种写法都安全,let 都会为每次迭代生成独立绑定:
-
for (let i = 0; i console.log(i), 100); }→ 输出 0、1、2 -
const arr = ['a', 'b', 'c']; for (let item of arr) { setTimeout(() => console.log(item), 100); }→ 输出 'a'、'b'、'c'
注意:for...in 不推荐用于数组,且 let 在其中的行为与 for...of 一致,但语义不匹配,应避免。
let 在 while 或 do...while 中不自动创建新绑定
while 循环本身没有“每次迭代块”的语法结构,所以即使写 let i = 0 在循环体内,也只声明一次;若想模拟每次迭代独立,需手动加块:
- ❌ 错误(i 仍被重复赋值,无新绑定):
let i = 0; while (i console.log(i), 100); i++; } - ✅ 正确(显式块确保每次新建作用域):
let i = 0; while (i console.log(current), 100); } i++; }
实际开发中要注意的边界情况
let 的块级绑定虽强大,但仍有细节需留意:
- 不能在声明前访问(暂时性死区 TDZ),
console.log(j); let j = 1;会报错 - 同一作用域内不可重复声明:
let x = 1; let x = 2;报错;但不同迭代块中互不影响 - 在 for 循环中,let 声明的变量在每次迭代开始时初始化,不是在条件判断后才绑定
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











