带let的循环JavaScript
我的JavaScript书籍《JavaScript权威指南》,第6版,第270页包含以下文本和代码: 。。。在for循环中,对初始值设定项表达式求值 超出新变量的范围 但是,当我在最新版本的Chrome和FF中运行上述代码时,会出现控制台错误: ReferenceError:未定义x 初始化前无法访问词法声明“x” 书中的代码不正确吗?这本书的勘误表站点上没有关于:this的内容。唯一的问题是,正如Jonas上面提到的那样,x被重新声明为Shadow,因此它抛出了一个错误 只需移除第二个let,一切都将按预期工作带let的循环JavaScript,javascript,let,Javascript,Let,我的JavaScript书籍《JavaScript权威指南》,第6版,第270页包含以下文本和代码: 。。。在for循环中,对初始值设定项表达式求值 超出新变量的范围 但是,当我在最新版本的Chrome和FF中运行上述代码时,会出现控制台错误: ReferenceError:未定义x 初始化前无法访问词法声明“x” 书中的代码不正确吗?这本书的勘误表站点上没有关于:this的内容。唯一的问题是,正如Jonas上面提到的那样,x被重新声明为Shadow,因此它抛出了一个错误 只需移除第二个let,
let x = 1;
for (x = x + 1; x < 5; x++) {
//^---- note the missing "let" here.
console.log(x); // prints 2, 3, 4
}
如果你是从一本书上抄来的,那就是一本书
有关变量声明的更多信息,请参见:
有关变量阴影的更多信息:
唯一的问题是,正如上面Jonas提到的那样,x被重新声明为阴影,因此它会抛出一个错误
只需移除第二个let,一切都将按预期工作
let x = 1;
for (x = x + 1; x < 5; x++) {
//^---- note the missing "let" here.
console.log(x); // prints 2, 3, 4
}
如果你是从一本书上抄来的,那就是一本书
有关变量声明的更多信息,请参见:
有关变量阴影的更多信息:
您两次初始化x,因此出现错误。将一个x重命名为i 设x=1; 对于设i=x+1;i<5;i++{ console.logi;//打印2、3、4
} 您初始化x两次,因此出现错误。将一个x重命名为i 设x=1; 对于设i=x+1;i<5;i++{ console.logi;//打印2、3、4
} 问题是您在for循环中重新声明了x,并且由于let只存在于给定的上下文中,因此在循环完成后,x不再存在 在for循环之外声明x一次,或者使用var.var将变量添加到全局范围,这样在for循环完成后它就会存在 设x=1; 对于x=x+1;x<5;x++{}
console.logx 问题是您在for循环中重新声明了x,并且由于let只存在于给定的上下文中,因此在循环完成后,x不再存在 在for循环之外声明x一次,或者使用var.var将变量添加到全局范围,这样在for循环完成后它就会存在 设x=1; 对于x=x+1;x<5;x++{}
console.logx 问题并不是x被声明了两次。只是您试图在初始化内部x之前访问它:
let x = x /* doesn't exist yet*/;
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声明之间的部分称为时间死区
。。。在for循环中,初始值设定项表达式在新变量的范围之外求值
否,否则无法引用初始值设定项中的其他变量:
for(let a = 1, b = a; ; )
与往常一样,明确的答案可以在规范中找到:
13.7.4.7运行时语义:标签化
迭代语句:用于词汇还原表达式;表达式语句
让oldEnv成为正在运行的执行上下文的词典环境
让loopEnv成为NewDeclarativeEnvironmentoldEnv
[……]
让boundNames成为词汇词典的boundNames
对于boundNames[…]的每个元素dn
表演!loopEnvRec.CreateImmutableBindingdn,true
将正在运行的执行上下文的LexicalEnvironment设置为loopEnv
让forDcl作为计算词汇退化的结果
[……]
如您所见,运行的执行上下文是loopEnv,而初始值设定项的LexicalDeclaration得到计算,而不是oldEnv
TLDR:不仅示例是错误的,段落也是错误的。问题并不是x被声明了两次。只是您试图在初始化内部x之前访问它:
let x = x /* doesn't exist yet*/;
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声明之间的部分称为时间死区
。。。在for循环中,初始值设定项表达式在新变量的范围之外求值
否,否则无法引用初始值设定项中的其他变量:
for(let a = 1, b = a; ; )
与往常一样,明确的答案可以在规范中找到:
13.7.4.7运行时语义:标签化
迭代语句:用于词汇还原表达式;表达式语句
让oldEnv成为正在运行的执行上下文的词典环境
让loopEnv成为NewDeclarativeEnvironmentoldEnv
[……]
让boundNames成为词汇词典的boundNames
为了
boundNames[…]的每个元素dn
表演!loopEnvRec.CreateImmutableBindingdn,true
将正在运行的执行上下文的LexicalEnvironment设置为loopEnv
让forDcl作为计算词汇退化的结果
[……]
如您所见,运行的执行上下文是loopEnv,而初始值设定项的LexicalDeclaration得到计算,而不是oldEnv
TLDR:不仅示例是错误的,而且段落也是错误的
书中的代码不正确吗?这本书的勘误表上没有关于:这个
我相信这些书是正确的;几年前在Firefox中首次引入let时
具体地说,它没有,而且它在内部的行为更像var,只是块作用域
在Firefox 44中,有一个突破性的变化,使得let和const遵循以下标准:
包括引入时间死区
所以,是的,这本书现在是不正确的;因为你想做一些事情,比如:
let x = 0;
{
let y = x; // `let` is block-scope,
// so this `x` is actually the `x`
// defined below, not the one outside
// the scope, hence the `ReferenceError`.
let x = 1;
}
书中的代码不正确吗?这本书的勘误表上没有关于:这个
我相信这些书是正确的;几年前在Firefox中首次引入let时
具体地说,它没有,而且它在内部的行为更像var,只是块作用域
在Firefox 44中,有一个突破性的变化,使得let和const遵循以下标准:
包括引入时间死区
所以,是的,这本书现在是不正确的;因为你想做一些事情,比如:
let x = 0;
{
let y = x; // `let` is block-scope,
// so this `x` is actually the `x`
// defined below, not the one outside
// the scope, hence the `ReferenceError`.
let x = 1;
}
x正在重新申报,这就是问题所在。@briosheje不,它没有重新申报。“它被遮蔽了。”乔纳斯威尔斯说得没错。尽管问题仍然存在。它被局部x变量遮挡了,对吗?@briosheje问题是试图访问其初始值设定项中的变量。引用的段落是错误的。谢谢大家!这对我来说更有意义了。我现在对关键字let的行为有了更好的理解!x正在重新申报,这就是问题所在。@briosheje不,它没有重新申报。“它被遮蔽了。”乔纳斯威尔斯说得没错。尽管问题仍然存在。它被局部x变量遮挡了,对吗?@briosheje问题是试图访问其初始值设定项中的变量。引用的段落是错误的。谢谢大家!这对我来说更有意义了。我现在对关键字let的行为有了更好的理解!如果没有时间死区,它forlet x=x将只是未定义的,for循环初始值设定项的计算必须已更改为如前所述,let只是在内部被视为具有某些块范围功能的var。具体地说,在循环的情况下,让x=x+1将从范围之外获取x+1中的x,因为它尚未声明。我不是说这是一个好的行为,我只是说这就是let的第一个实现是如何工作的。您可以使用实现遗留let的Firefox版本来测试自己:在这种情况下,书中的代码在书中指定的意义上是正确的。如果没有时间死区,它forlet x=x将只是未定义,for循环初始值设定项的评估必须更改为,let在内部看起来就像一个具有某些块作用域功能的var。具体地说,在循环的情况下,让x=x+1将从范围之外获取x+1中的x,因为它尚未声明。我不是说这是一个好的行为,我只是说这就是let的第一个实现是如何工作的。您可以使用实现legacy let的Firefox版本来测试自己:在这种情况下,书中的代码是正确的,正如书中所指定的那样。