让 JavaScript for 循环中的变量

问题描述

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

当 "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();

解决方法

如果 JS 在使用 let 时在 for 循环的每次迭代中都创建了一个新的“i”绑定,那么增加的值是如何传递给新的 i 绑定的?

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

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

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

您会在ES262,13.7.4.9 Runtime Semantics: CreatePerIterationEnvironment

中找到这一切 ,

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

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。此变量由循环中对象属性 for 的最新(在 o.i 循环中)值更新,然后按值传递到console.log() 函数。与此相反,表达式 console.log(i,o.i) 将在稍后执行,当 setTimeOut() 函数触发时。到那时,对象 i 的属性 o 将是 3