所以我注意到我必须在for
循环中使用const
,并且不能使用const
。但是,我发现我可以在for-in
和for-of
结构(下面的代码)中使用for
。直观地说,我可以理解这是因为// Doesn't work
for (const i = 0; i < 3; i++) {
console.log(i);
}
// Works
for (let i = 0; i < 3; i++) {
console.log(i);
}
// Works
const object2 = ['a', 'b', 'c'];
for (const v of object2) {
console.log(v);
}
// Works
const object3 = {
a: 'a',
b: 'b',
c: 'c',
};
for (const v in object3) {
console.log(v);
}
循环以不同的方式实现/更原始,而其他构造desugar到for循环,其中迭代变量在for循环的顶部分配。
let
我在Mozilla MDN上唯一能找到的就是for循环页面:
此表达式可以选择使用var声明新变量 关键词。这些变量不是循环的局部变量,即它们在 与for循环相同的范围。此表达式的结果是 丢弃。
这似乎也是错误的,因为如果我们使用i
i
,则for
循环后for (let i = 0; i < 3; i++) {
console.log(i);
}
// Doesn't work as expected
console.log(i);
不再在{{1}}循环中(与其他语言一致) )
{{1}}
我的问题是这个行为是否在某个地方的规范中是预期和定义的? MDN对此没有太多说明。
答案 0 :(得分:3)
是。这确实是预期的行为。
const
定义一个变量,顾名思义,该变量保持不变。这意味着const的值不能改变。
现在你在for
循环中所做的是递增&#34; i&#34;,它被定义为常量。
for (const i = 0; i < 3; i++ /* <- this doesn't work */ ) {
console.log(i);
}
使用for .. in
或for .. of
但是,您只需绑定变量。
换句话说:对于for .. in/off
,变量在执行循环之前被分配一次,而不是在每次迭代时分配。因此确实可以使用const
。
至于参考:
ForDeclaration:LetOrConst ForBinding
答案 1 :(得分:2)
根据spec
for-in 和 for-of 语句允许ForDeclaration:LetOrConst ForBinding
let
和const
。
另外,根据spec中提到的运行时语义
对于ForBinding的BoundNames的每个元素名称
此表达式for (const v in object3) {
为每次迭代执行并提供新的绑定。
但是,使用简单的for循环 - for (const i = 0; i < 3; i++) {
, const i
只执行一次和因此它不允许您要为其重新分配值。
答案 2 :(得分:1)
你的第一个问题已由@NullDev回答,所以我要去第二个问题:
此表达式可以选择使用var声明新变量 关键词。这些变量不是循环的局部变量,即它们在 与for循环相同的范围。此表达式的结果是 丢弃。
“这些变量不是循环的局部变量”是指var
关键字创建的计数器。如果使用let
,则计数器的范围仅在for循环中。这是另一个预期的行为,因为var
具有无广泛的范围。是的,文档有点含糊不清。
答案 3 :(得分:1)
所以我注意到我必须在for循环中使用let,并且不能使用const。
没有。你可以在const
循环中使用for
声明就好了。问题只是const
声明了一个常量绑定,因此增量i++
不会对const i
起作用(它应该抛出异常,确保你在严格模式)。
如何使用const
:
for (const o = {index: 0, value: null}; o.index < arr.length; o.index++) {
o.value = arr[o.index];
doSomething(o);
}
或者更有意义的地方:
for (const iterator = makeIterator(); !iterator.isDone(); iterator.next())
doSomething(iterator.getCurrent());
}
直观地说,我可以理解这是因为for循环以不同的方式实现/更原始,而其他构造desugar到for循环,其中迭代变量在for循环的顶部分配。
是。在for
循环中,您需要自己更新迭代变量。
for ([var] init; condition; update) { body }变
[var] init; while (condition) { body; update; }
for (const init; condition; update) { body }
变为
{ const init; while (condition) { body; update; } }
for (let init; condition; update) { body }
在for … in
和for … of
循环中,您只需为生成的值声明一个赋值目标表达式。
for ([var]/let/const target of iterable) { body }
变为
{ const _iterator = iterable[Symbol.iterator](); let _result; while (!(_result = _iterator.next()).done) { [var]/let/const target = _result.value; body; } }
for (… in enumerable)
与for (… of Reflect.enumerate(enumerable))
相同。
我在Mozilla MDN上唯一能找到的就是
for
循环页面,这似乎也是错误的。
是的,看起来该部分尚未针对ES6进行更新。