让变量在 JavaScript for 循环中

Let variable in a JavaScript for loop

我检查了关于同一问题的问题和答案,但没有一个回答我的问题,所以请不要丢弃我的问题。

当 "i" 被声明为 let 变量时,对于每次迭代,JS 都会创建一个新的 "i" 绑定, 因此 SetTimout 的每个函数在其闭包中都有自己的“i”(与“i”被声明为 var 变量的情况相反,在这种情况下所有 SetTimout 函数在其闭包中共​​享相同的绑定)。 问题是 : 如果JS在使用let时for循环的每次迭代都创建一个新的“i”绑定,那么增加的值如何传递给新的绑定i?

如何用 i 的当前值实例化 i 的新绑定?

我们真的在不同的范围内有两个具有不同值的 i 绑定吗?如果是,那些范围是什么?

提前致谢

function a() {

    for (let i = 0; i < 3; i++) {
        setTimeout(function () { console.log(i) }, i * 1000);
    }
}

a();

If JS creates a new binding of "i" at each iteration of the for loop when using let, so how the incremented value is transmitted to the new binding of i ?

在迭代结束时,值会从上一个环境记录复制到下一个环境记录。

Do we really have two binding of i in different scopes with different values if yes what are those scopes?

我想在这里介绍术语环境记录,这是规范用来描述绑定值的“事物”的术语。有多个环境记录(每次迭代一个),它们都具有相同的范围(可以在循环体内访问值),并且可能有不同的生命周期和值。

你会在 ES262, 13.7.4.9 Runtime Semantics: CreatePerIterationEnvironment

中找到所有这些

您在 let 的块作用域内声明的任何内容都只会在那里可用。但它将是一个 单一 实例。在你的例子中,你给你的 console.log() 函数的参数是一个简单的值(而不是一个对象),因此它是在 for 循环中调用时“按值”传递的。值为 012。如果你看一下我修改过的类似循环的例子,你会注意到在我的例子中每个 setTimeOut() 调用将引用同一个对象 o 并且 属性 o.i 被访问在执行时,对于所有树调用,它将是 3o.i 循环结束后的值)。

for (let i,o={i:0}; o.i < 3; o.i++) { 
    i=o.i;
    setTimeout(function () { console.log(i,o.i) }, o.i * 1000);
}

为了演示按值传递按引用传递之间的区别,我将局部变量i添加到混合。该变量由循环中对象 属性 o.i 的最新(在 for 循环中)值更新,然后被 传递value 到 console.log() 函数。相反,当 setTimeOut() 函数触发时,表达式 console.log(i,o.i) 将在稍后执行。到那时对象 o 的 属性 i 将是 3.