CodeWalk

for 循环中使用 var 和 let 声明变量的区别(附闭包解释)

作者:Yahuda · 2026-05-30 12:55

如下代码分别使用 var 和 let 运行,结果有何不同?为什么?

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 100);
}

回答

Yahuda

结果:var 输出 3 3 3,let 输出 0 1 2

原因

  1. var:没有块级作用域,i 存在于全局/函数作用域中。循环结束时 i=3,三个定时器回调共享同一个 i,所以都输出 3。
  2. let:具有块级作用域,每次循环都创建独立的词法环境。setTimeout 回调通过闭包捕获了每次迭代中独立的 j 值。

浏览器兼容机制

  • 规范要求 for (let ...) 每次迭代创建新的词法环境,并在环境内绑定当前值
  • 用 var 的等价修复方式:使用 IIFE 创建闭包
for (var i = 0; i < 3; i++) {
  (function(i) {
    setTimeout(() => console.log(i), 100);
  })(i);
}