所以我的代码中出现x is not defined
错误,这使我有些困惑,因为之前已经定义了x
几行。我不得不花一些时间来调整代码,删除和添加行,直到我了解了为什么会这样。删除所有不必要的信息后,现在代码如下所示:
let foo = 2;
console.log(foo);
if (foo === 2){
console.log(foo);
let foo = 1;
}
它在第5行抛出foo is not defined
。当我尝试console.log(foo)
时,会弹出一个错误!如果我删除第6行let foo = 1;
,该代码将正常运行。我的意思是在我第二次声明foo
之前发生了错误。所以第一个问题是:
我不明白的第二件事是为什么它说foo is not defined
而不是foo has been already declared
。如果我将第二个let
替换为var
,则会在第6行出现错误,并显示foo has been already declared
,因此看起来不错。但是将let
设置为第二个标识符始终会引发错误错误。
在测试了不同的场景之后,我注意到结果取决于我使用的标识符:
identifiers | result
----------------------------------------------
var var | the code works well
var let | not defined error
let var | has been already declared error
let let | not defined error
第三个问题是:
var
,所以重复使用var
是代码完美运行的唯一方法吗?这是个例外吗?
- 第6行(尚未执行)如何使第5行以错误结尾?
因为用let
,const
和class
声明的绑定范围(松散地是“变量”)是整个块,而不仅仅是从声明它们的位置到块的末尾。代码进入块与执行let
语句之间的时间称为Temporal Dead Zone(TDZ),在此期间绑定存在但未初始化,因此不能以任何方式使用。即使在代码流中遇到let foo
之前,仅在块中包含foo
也会遮盖外部let foo
。
除了作用域,此TDZ是var
和let
之间的最大区别是var
创建绑定and将其初始化为undefined
,无论var
语句在何处。范围。相比之下,let
(以及const
和class
)创建绑定,但是do n't初始化绑定,直到以后在遇到let
(const
,class
)时。代码的分步执行。您不能使用未初始化的绑定。
- 为什么会引发错误错误?
这是不正确的。您可能会说它措辞不佳。 :-)基本上是说“您不能在这里使用foo
,它没有被初始化。”在我看来,来自V8(Chrome,Chromium,Brave,新的基于Chromium的Edge和Node.js的JavaScript引擎)的当前错误消息更加清晰:
未捕获的ReferenceError:初始化前无法访问'foo'
当使用let
声明变量时,它在当前代码块的范围内有效。您的第二个let foo
声明定义了与第一个变量不同的foo
,并且仅在if块内有效。但是,您在定义它之前就在使用它,因此您会正确地得到尚未定义的错误。
[如果您确实打算有两个不同的foo
变量,我建议您将它们称为其他名称(例如foo1和foo2),以避免冲突。然后很明显,您在定义变量之前就在使用它。
let foo1 = 2;
console.log(foo1);
if (foo1 === 2){
console.log(foo1);
let foo2 = 1;
}
[如果您想让第5行使用foo
的第一个实例设置为2,那么您已经通过if块中发生的新定义将其隐藏了。
如果要在第5行上使用foo
设置为1,则应在使用前将其定义移至。
请注意,使用var
会产生不同的结果,因为var
变量的范围比let
变量的范围更广。参见具有以下定义的here:
让您可以声明限于变量范围的变量块语句或使用它的表达式,与var不同关键字,用于全局或局部定义整个变量功能,与块范围无关。