让变量在 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
循环中调用时“按值”传递的。值为 0
、1
和 2
。如果你看一下我修改过的类似循环的例子,你会注意到在我的例子中每个 setTimeOut()
调用将引用同一个对象 o
并且 属性 o.i
被访问在执行时,对于所有树调用,它将是 3
(o.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
.
我检查了关于同一问题的问题和答案,但没有一个回答我的问题,所以请不要丢弃我的问题。
当 "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
循环中调用时“按值”传递的。值为 0
、1
和 2
。如果你看一下我修改过的类似循环的例子,你会注意到在我的例子中每个 setTimeOut()
调用将引用同一个对象 o
并且 属性 o.i
被访问在执行时,对于所有树调用,它将是 3
(o.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
.