考虑以下代码片段:
for (let i = 0; i < 5; i++) {
i+=1;
setTimeout(() => console.log(i), 100);
}
console.log('after for loop');
如果let i
每次迭代都会创建一个新的 block 作用域变量,我希望它输出:
1
2
3
4
5
因为,作为一个新的 block 作用域变量,i+=1;
只会对我的本地副本 i
进行更改。另外,如果i
是一个新的 block 作用域变量,这可以解释为什么 setTimeout
回调不会记录“6”3次(就像 let i
更改为 var i
一样)。
如果它有帮助,这是我想象的,如果它为每次迭代创建一个新的 block 作用域变量,它会在后台执行以下操作:
for (let I = 0; I < 5; I++) {
let i = I;
i+=1;
setTimeout(() => console.log(i), 100);
}
console.log('after for loop');
但是,顶部片段实际上输出:
1
3
5
如果 i
就有意义了在所有迭代之间共享,除非 i
在所有迭代之间共享为什么 setTimeout
回调不会打印相同的数字 3 次?
简而言之,我的问题是:
为什么在顶部片段中是 i+=1;
都更新循环变量,就像i
一样在i+=1;
不是每次迭代的本地副本,并且也表现在 setTimeout
中回调就像 i
是每次迭代的本地副本。
最佳答案
当变量在 for
中声明时循环声明在循环体内重新分配,该重新分配将持续到下一次迭代。如果你看一下 Babel 就更清楚了转译它:
for (let i = 0; i < 5; i++) {
i+=1;
setTimeout(() => console.log(i), 100);
}
console.log('after for loop');
结果
"use strict";
var _loop = function _loop(_i) {
_i += 1; // <---------------
setTimeout(function() {
return console.log(_i);
}, 100);
i = _i; // <---------------
};
for (var i = 0; i < 5; i++) {
_loop(i);
}
console.log("after for loop");
如果您更改或记录i
在 for
的同步执行之外循环体,它将(本质上)引用 _i
上面,就像一个完全独立的 block 作用域变量。但如果你改变 i
内部同步for
循环体,下一次迭代将从更改后的 i
开始.
关于javascript - 为什么 "for (let i..."中的 i 有时表现得像 block 作用域,但其他时候却不然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56894272/