Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带let的循环JavaScript_Javascript_Let - Fatal编程技术网

带let的循环JavaScript

带let的循环JavaScript,javascript,let,Javascript,Let,我的JavaScript书籍《JavaScript权威指南》,第6版,第270页包含以下文本和代码: 。。。在for循环中,对初始值设定项表达式求值 超出新变量的范围 但是,当我在最新版本的Chrome和FF中运行上述代码时,会出现控制台错误: ReferenceError:未定义x 初始化前无法访问词法声明“x” 书中的代码不正确吗?这本书的勘误表站点上没有关于:this的内容。唯一的问题是,正如Jonas上面提到的那样,x被重新声明为Shadow,因此它抛出了一个错误 只需移除第二个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版本来测试自己:在这种情况下,书中的代码是正确的,正如书中所指定的那样。