在使用let声明时,在初始化区域中声明的语句的语义是什么?

3

我知道当我在循环中声明一个let变量时,该变量会在每个周期中被声明。例如:

for(let i=0 ; i<3 ; i++)
{
    let x=1;
}

变量x在循环中声明了3次,每个变量分配了不同的内存空间。

但是变量i会发生什么?它只声明一次吗? 还是只初始化一次,但也声明了三次?

我想了解背后发生了什么。


i 只被声明了一次,x 被再次声明了,但不用担心。内部的 V8 引擎或者你的浏览器所使用的引擎会对 x 进行优化。 - Keith
同样也是局部变量,属于循环块的环境,这种情况下也会创建三个名为 i 的变量。 - ASDFGerte
注意:不是直接的重复,但非常相关 - javascript-closure-inside-loops-simple-practical-example - ASDFGerte
2个回答

3

使用 let 关键字,i 只会被声明一次,并且每个循环都会得到一个新的绑定。它的作用域仅限于块级语句内部。

来自ECMAScript 6 中的变量和作用域

在循环中,如果你使用 let 声明一个变量,那么每次迭代都会获得一个新的 绑定。允许你这样做的循环有:forfor-infor-of

for (let i = 0; i < 3; i++) {
    let x = 1;
    setTimeout(() => console.log(i), 1000);
}

以下是与创建新绑定有关的赋值示例。

for (let x = { v: 0 }; x.v < 2; x.v += 1) {
    setTimeout(() => console.log(x), 100); // same values
}

for (let x = { v: 0 }; x.v < 2; x = { v: x.v + 1}) {
    setTimeout(() => console.log(x), 100); // different values
}
.as-console-wrapper { max-height: 100% !important; top: 0; }


1
我认为你可以使用逗号运算符进行测试(可能类似于这个),它说它只初始化一次? - Nick Parsons
1
@MickaelB。请不要将w3schools作为超越基础知识的任何内容的参考。请参见元主题。它们不是一个好的来源。 - ASDFGerte
1
我不确定这是否正确,否则这段代码就行不通了-> for (let x={v:0}; x.v < 10; x.v += 1) { console.log(x);} ,除非浏览器将其变成了const,.. 无论如何,当不需要时进行复制似乎非常浪费。 - Keith
1
@NickParsons 值被复制,初始化不会再次执行,请参见13.7.4.9 运行时语义:CreatePerIterationEnvironment - ASDFGerte
1
准确地 - Nina Scholz
显示剩余14条评论

0

如果你使用 leti 将在每个循环中声明。

如果你使用 vari 只会被声明一次。

如果你使用 consti 不会在每个循环中被声明(它的作用域与循环相同)。尝试这样做,你将会得到一个错误:

for (const i = 0; i < 9; i++) {
   console.log(i);
   // more statements
}

错误:未捕获的类型错误:常量变量赋值。

参考此处


4
这里的错误在于 i++,即对一个常量变量进行修改。 - Nick
@Umbert,你是正确的,我已经编辑了我的答案。 - leosbrf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接