Javascript ECMAScript 2015:for 循环中的常量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31987465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ECMAScript 2015: const in for loops
提问by adrianp
Which of the two (or neither/ both) code fragments below should be working in a complete ECMAScript 2015 implementation:
下面的两个(或两个都不是)代码片段中的哪一个应该在完整的 ECMAScript 2015 实现中工作:
for (const e of a)
for (const e of a)
for (const i = 0; i < a.length; i += 1)
for (const i = 0; i < a.length; i += 1)
From my understanding, the first example should work because e
is initialized for each iteration. Shouldn't this also be the case for i
in the second version?
根据我的理解,第一个示例应该可以工作,因为e
每次迭代都会初始化。i
在第二个版本中不应该也是这种情况吗?
I'm confused because existing implementations (Babel, IE, Firefox, Chrome, ESLint) do not seem to be consistent and have a complete implementation of const
, with various behaviours of the two loop variants; I'm also not able to find a concrete point in the standard, so that would be much appreciated.
我很困惑,因为现有的实现(Babel、IE、Firefox、Chrome、ESLint)似乎不一致并且具有 的完整实现const
,以及两个循环变体的各种行为;我也无法在标准中找到具体的点,因此将不胜感激。
回答by lyschoening
The following for-of loop works:
以下 for-of 循环有效:
for (const e of a)
The ES6 specification describes this as:
ES6 规范将其描述为:
ForDeclaration : LetOrConst ForBinding
ForDeclaration : LetOrConst ForBinding
The imperative for loop will not work:
命令式 for 循环不起作用:
for (const i = 0; i < a.length; i += 1)
This is because the declaration is only evaluated once before the loop body is executed.
这是因为在执行循环体之前,声明只被评估一次。
回答by Bergi
I won't cite the spec this time, because I think it's easier to understand what happens by example.
这次我不会引用规范,因为我认为通过示例更容易理解发生了什么。
for (const e of a) …
for (const e of a) …
Is basically equivalent to
基本上相当于
{
const __it = a[Symbol.iterator]();
let __res;
while ((__res = __it.next()) && !__res.done) {
const e = __res.value;
…
}
}
For simplicity I've ignored that there's a TDZ with e
for the a
expression, and the various __it.return()
/__it.throw(e)
calls in the case the loop exits prematurely (break
or throw
in the body).
为简单起见,我忽略e
了a
表达式的 TDZ ,以及在循环过早退出(或在主体中)的情况下的各种__it.return()
/__it.throw(e)
调用。break
throw
for (const i = 0; i < a.length; i += 1) …
for (const i = 0; i < a.length; i += 1) …
is basically equivalent to
基本上相当于
{
const i = 0;
while (i < a.length) {
…
i += 1;
}
}
In contrast to let
, a const
declaration in a for
loop does not get redeclared in every loop iteration (and the initialiser is not re-executed anyway). Unless you break
in the first iteration, your i +=
will throw here.
与 相比let
,循环中的const
声明for
不会在每次循环迭代中重新声明(并且初始化程序无论如何都不会重新执行)。除非你break
在第一次迭代中,否则你i +=
会抛出这里。
回答by Kit Sunde
Your second example should definitely not work because i
is declared once and not on each iteration this is just a function of how that category of loops work.
您的第二个示例绝对不应该工作,因为i
声明一次而不是在每次迭代时,这只是该类循环如何工作的函数。
You can try this in a regular browser:
您可以在常规浏览器中尝试此操作:
for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){
console.log(otherVar)
otherVar = "If otherVar was initialized on each iteration, then you would never read me.";
}
It's not the case that const
is entirely disallowed in for
loops. Only for
that will modify const is.
const
在for
循环中并不是完全不允许的情况。只有for
那会修改 const 是。
These are valid:
这些是有效的:
for(const i = 0;;){ break }
for(const i = 0; i < 10;){ break; }
These are invalid:
这些是无效的:
for(const i = 0;;){ ++i; break; }
for(const i = 0;;++i){ if(i > 0) break; }
I'm not sure why Firefox gives a SyntaxError after reading the ES2015 spec (although I'm sure the clever folk at Mozilla are correct), it seems like it's supposed to raise an exception:
我不知道为什么 Firefox 在阅读 ES2015 规范后会给出 SyntaxError(虽然我确信 Mozilla 的聪明人是正确的),它似乎应该引发异常:
Create a new but uninitialized immutable binding in an Environment Record. The String value N is the text of the bound name. If S is true then attempts to access the value of the binding before it is initialized or set it after it has been initialized will always throw an exception, regardless of the strict mode setting of operations that reference that binding. S is an optional parameter that defaults to false.
在环境记录中创建一个新的但未初始化的不可变绑定。字符串值 N 是绑定名称的文本。如果 S 为真,则尝试在初始化之前访问绑定的值或在初始化之后设置它总是会抛出异常,无论引用该绑定的操作的严格模式设置如何。S 是可选参数,默认为 false。