JavaScript for 循环是否会在每次迭代中重新声明变量?

问题描述 投票:0回答:2

我试图理解 JavaScript 中的闭包,并遇到了这个例子:

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

由于变量

i
的作用域为
for
循环,因此在每次迭代中都会给它一个新的引用,因此它不会在迭代之间共享,因此闭包捕获
log
函数以及对每次迭代中的
i
变量。

正如预期的输出是:

$ 0
$ 1
$ 2

但是,在以下代码片段中,行为有所不同:

for (let arr = [1, 2, 3]; arr.length !== 0; arr.pop()) {
    const log = () => {
        console.log(arr);
    };
    setTimeout(log, 1000);
}

预期输出是

$ [1, 2, 3]
$ [1, 2]
$ [1]

但是我得到了 3 个带有空数组的日志,这表明

arr
变量可能在迭代之间共享。

javascript node.js loops for-loop closures
2个回答
1
投票

不同之处在于,i 是一个整数,作为复制参数传递给另一个函数。 arr 是作为参考参数传递的数组。

所以超时后,即使原始值改变了,副本也没有改变,但引用的却改变了。

https://javascript.info/object-copy#:~:text=One%20of%20the%20fundamental%20差异,%E2%80%9Cas%20a%20whole%20value%E2%80%9D.


1
投票

您的

arr
变量在循环的每次迭代中都会初始化为数组的 reference。它确实在每次迭代中都是一个不同的变量,但只有一个数组,并且您的循环在每次迭代时都会弹出一个值。因此,当计时器触发时,数组已空。

for
循环中的局部作用域变量如何工作的精确细节有点复杂。初始化表达式计算一次(我很确定;规范很难阅读),然后在每次迭代时创建一个新变量并将其初始化为前一个变量的值。因此,在数组引用的情况下,变量的直接值不会改变。如果您可以以某种方式执行“last_variable === this_variable”测试(您不能),那么迭代之间将是
true
,因为它是相同的数组。但如果是原始值,那就不一样了。

© www.soinside.com 2019 - 2024. All rights reserved.