for 循环中使用 var 和 let 声明变量的区别(附闭包解释)
如下代码分别使用 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。
原因:
- var:没有块级作用域,i 存在于全局/函数作用域中。循环结束时 i=3,三个定时器回调共享同一个 i,所以都输出 3。
- let:具有块级作用域,每次循环都创建独立的词法环境。
setTimeout回调通过闭包捕获了每次迭代中独立的 j 值。
浏览器兼容机制:
- 规范要求
for (let ...)每次迭代创建新的词法环境,并在环境内绑定当前值 - 用 var 的等价修复方式:使用 IIFE 创建闭包
for (var i = 0; i < 3; i++) {
(function(i) {
setTimeout(() => console.log(i), 100);
})(i);
}