javascript - 为什么 "for (let i..."中的 i 有时表现得像 block 作用域,但其他时候却不然

标签 javascript for-loop

考虑以下代码片段:

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/

相关文章:

java - 显示带有嵌套 for 循环的 ASCII 菱形

php - 循环遍历复选框并在 'ID' = ='ID' 时显示已选中

javascript - 如何在代码中使用 For 循环?

javascript - Bower/grunt 在顶部加载 1 个脚本

javascript - 提取 Javascript 数组

javascript - d3.csv 无法上一级目录

javascript - Javascript 中最长的公共(public)前缀

javascript - 屏幕上的图像叠加切换按钮

javascript - 我如何在 vue-router beforeEach 中使用 vuex Action

javascript - 当 ( for in ) 执行 javascript 时如何做某事?