结尾的行(尚未执行)如何可能影响代码的开头?为什么它会抛出一个错误



所以我的代码中有一个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之前会发生错误。所以第一个问题是:

  1. 第6行(尚未执行(怎么可能导致第5行出现错误

我不明白的第二件事是为什么它说的是foo is not defined而不是foo has been already declared。如果我用var替换第二个let,第6行将出现一个错误,它会说foo has been already declared,所以看起来很好。但是,将let设置为第二标识符总是会引发错误。

  1. 为什么会抛出错误

在测试了不同的场景后,我注意到结果取决于我使用的标识符:

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

所以第三个问题是:

  1. 为什么每个人都反对使用var,而在这种情况下,双重使用var是代码完美工作的唯一方式?这是个例外吗
  1. 第6行(尚未执行(怎么可能导致第5行出现错误

因为用letconstclass声明的绑定(松散地称为"变量"(的范围是整个块,而不仅仅是从声明它们的位置到块的末尾。代码进入块和执行let语句之间的时间称为时间死区(TDZ(,在此期间绑定存在,但未初始化,不能以任何方式使用。即使在代码流中遇到let foo之前,仅在块中具有let foo就遮蔽了外部foo

除了作用域之外,这个TDZ是varlet之间的最大区别,var创建了一个绑定,并且将其初始化为undefined,而不管var语句在作用域中的什么位置。相反,let(以及constclass(创建绑定,但直到稍后在代码的逐步执行中遇到let(constclass(时才初始化它。不能使用未初始化的绑定。

  1. 为什么会抛出错误

这没有错。你可以说它措辞拙劣基本上,它是在说"你不能在这里使用foo,它没有初始化。"在我看来,来自V8(Chrome、Chromium、Brave、新的基于Chromium的Edge和Node.js中的JavaScript引擎(的当前错误消息更清楚:

未捕获引用错误:在初始化之前无法访问"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行使用设置为2的foo的第一个实例,那么您已经通过If代码块中发生的新定义将其隐藏。

如果您的意思是在第5行使用设置为1的foo,那么您应该在使用之前将其定义移动到。

注意,使用var具有不同的结果,因为var变量的范围比let变量的范围宽。见这里有这个定义:

let允许您声明限制在block语句或使用它的表达式,与var不同关键字,它全局地或局部地定义一个变量函数,而与块范围无关。

为了让它更清楚,我用代码每个阶段的变量状态标记了您的代码:

let foo = 2;          // foo defined and set to 2
console.log(foo);     // foo defined and set to 2
if (foo === 2)        // foo defined and set to 2
{                     // <-- start of the if-block!
console.log(foo); // foo not defined yet
let foo = 1;      // foo defined and set to 1
}                     // <-- end of if-block!
console.log(foo);     // foo defined and set to 2

相关内容

最新更新