我的 JavaScript 书“JavaScript 权威指南,第 6 版”,第 270 页包含以下文本和代码:
"... 在 for 循环中,对初始化表达式求值 在新变量的范围之外”
let x = 1;
for (let x = x + 1; x < 5; x++) {
console.log(x); // prints 2, 3, 4
}
但是,当我运行上面的代码(在最新版本的 Chrome 和 FF 中)时,出现控制台错误:
ReferenceError: x is not defined
can't access lexical declaration `x' before initialization
书上的代码有错吗? (本书的勘误网站上没有任何内容 re: this。)
最佳答案
问题不在于 x
被声明了两次。这只是你试图在初始化之前访问内部 x
:
let x = x /* doesn't exist yet*/;
在外部作用域中是否有另一个 x
(for
循环中的初始化器在它们自己的作用域内)并不重要,x
将引用当前范围内的变量,因为它已经声明(由于提升),但尚未初始化:
let x = 0; // irrelevant
{ // x gets declared as part of this scope
x; // thats an error too as x is not initialized yet
let x = 1; // initialization
x; // now it can be accessed
}
范围开头和 let
声明之间的部分称为“临时死区”...
"... in a for loop, the initializer expression is evaluated outside the scope of the new variable"
不,否则你不能在初始化器中引用其他变量:
for(let a = 1, b = a; ; )
一如既往,可以在规范中找到明确的答案:
13.7.4.7 Runtime Semantics: LabelledEvaluation
IterationStatement : for ( LexicalDeclaration Expression ; Expression ) Statement
Let oldEnv be the running execution context's LexicalEnvironment.
Let loopEnv be NewDeclarativeEnvironment(oldEnv).
[...]
Let boundNames be the BoundNames of LexicalDeclaration.
For each element dn of boundNames [..]
Perform ! loopEnvRec.CreateImmutableBinding(dn, true).
Set the running execution context's LexicalEnvironment to loopEnv.
Let forDcl be the result of evaluating LexicalDeclaration.
[...]
如您所见,运行的执行上下文是 loopEnv
,而 LexicalDeclaration(初始化器)被评估,而不是 oldEnv
。
TLDR:不仅示例错误,段落也错误。
关于带有 let 的 JavaScript for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54653463/