JavaScript:理解 for 循环中的 let 范围

标签 javascript for-loop ecmascript-6 scope let

这个问题在这里已经有了答案:





Explanation of `let` and block scoping with for loops

(4 个回答)


2年前关闭。




请考虑下面的片段 -

for(let i = 1; i <= 5; i++) {
   setTimeout(function(){
       console.log(i);
   },100);
}

在这种情况下,在 setTimeout 内记录将包含变量 i 的值根据for循环的每次迭代,即日志如下
1
2
3
4
5

为此,我已经阅读了互联网上的解释,例如 - let为每个循环创建一个变量声明,这是 block 级声明。所以基本上它在 { } 内创建了一个范围.

但我对这个说法有点困惑。如果 let为每个循环创建一个变量声明,它不会总是初始化为 1根据循环初始化语句 let i=1 ?
此外,变量 i在循环 block 之外声明、初始化和递增,即 for 中的花括号循环语句。所以,在每次迭代中不是同一个变量i被增量和利用? let到底是怎么回事?为每个循环创建一个变量声明并具有先前迭代的值?

最佳答案

一般说明

当您使用 letfor像你展示的循环结构,有一个新变量 i为循环的每次调用创建,该循环的范围仅限于循环 block (在循环外不可访问)。

循环的第一次迭代从 for 中获取它的值。循环初始化程序( i = 1 在您的示例中)。其他新i每次循环迭代创建的变量从 i 获取它们的值。对于循环的先前调用,而不是来自 i = 1这就是为什么它们没有全部初始化为 1 .

因此,每次循环都会有一个新变量 i它与所有其他的分开,每个新的都用前一个的值初始化,然后由 i++ 处理在 for循环声明。

对于您的 ES6 代码:

for(let i = 1; i <= 5; i++) {
   setTimeout(function(){
       console.log(i);
   },100);
} 


在 ES5 中,这将是一个本质上等价的结构。如果你真的研究了这个,它可以为你上面的 ES6 代码中实际发生的事情提供非常丰富的信息:

(function() {
    for (var i = 1; i <= 5; i++) {
        i = (function(j) {
            setTimeout(function(){
                console.log(j);
            },100);
            return j;
        })(i);
    }
})();


它需要两个 IIFE(立即调用的函数表达式)来模拟这一点。外层隔离 var i这样它就不会从 for 中泄漏出来循环和内部循环为 for 的每次调用提供单独的范围和单独的变量环形。 return ji = (function(j) {...})(i)是显示循环的下一次迭代如何受到对循环变量的修改的影响。

希望这能说明 let 的有用性。适用于 for ES6 中的循环以及当您需要/想要此功能时它替换了多少其他代码。

现在针对您的具体问题

For this, I have read explanations over the Internet like - let creates a variable declaration for each loop which is block level declaration. So basically it creates a scope within { }


let定义具有 block 作用域的变量(不是函数作用域,如 var )。而且,{}描绘for循环确实定义了一个范围。

Also, variable i is declared, initialized and incremented outside the loop block i.e. curly braces in the for loop statement.



嗯,不完全是。 for循环是如何初始化第一个 i 的指令为第一次调用循环创建。事实上,let i = 1出现在循环之外确实看起来有点困惑,但它实际上只是一个关于创建第一个 i 时要做什么的说明。第一次调用循环的变量。那第一个i变量实际上并不存在于循环范围之外。

So, in each iteration isn’t the same variable i is incremented and utilized?



不会。当 ES6 遇到 for 时使用 let 循环定义,它为循环的每次迭代创建一个新变量。

How exactly does let creates a variable declaration for each loop and has value of previous iteration?



不是 let这样做。这是for ES6+ JS 解释器中的循环逻辑。这是 for 的特殊行为。具有用 let 声明的索引初始化程序的循环.所以,这是 let 的组合行为和 for ,但真正的逻辑是for循环由解释器执行。

修改循环变量时的特殊情况
let 还有一个特例在 for循环。如果您分配给 i 的值在循环中,它将更改 i 的特定值它还会影响下一次迭代的值i .这有点特殊,但它仍然允许您操纵 i 的值。在循环。

for(let i = 1; i <= 5; i++) {
   let j = i;
   setTimeout(function(){
       console.log(j);
   },100);
   if (i === 2) {
      i++;         // bump the loop increment to skip the 3 value
   }
}


这将创建输出:
1
2
4
5

所以,这会跳过 3循环的迭代,因为当 i === 2 ,我们将它增加到 3,然后 for循环执行其i++迭代并将其提升到 4 ,有效地跳过 3迭代。

关于JavaScript:理解 for 循环中的 let 范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59170277/

相关文章:

java - for循环Java返回值

javascript - 为什么 JavaScript 中 Set 中的项被称为 value 而不是 key?

Javascript 符号 : () => { return 5; }

javascript - 使用纯 javascript 查找 #wrapper 中是否有 img

javascript - 选中复选框后添加文本框

javascript - 在 Kendo UI Mobile kendoMobileListView 中,选择列表中的项目后清除可过滤输入字段

javascript - ES6 组件之间的 React setState

javascript - 如何检测已加载新内容以响应滚动触发器?

swift - 不重复地加载数据和追加

javascript - 将数组中的每个项目与数组的其余部分进行比较的最快方法?