Javascript 最后的行(尚未执行)如何可能影响代码的开头?为什么会抛出错误呢?
因此,我的代码中有一个Javascript 最后的行(尚未执行)如何可能影响代码的开头?为什么会抛出错误呢?,javascript,node.js,syntax-error,identifier,referenceerror,Javascript,Node.js,Syntax Error,Identifier,Referenceerror,因此,我的代码中有一个x未定义错误,这让我有点困惑,因为x之前已经定义了几行。我不得不花一些时间调整我的代码,删除和添加行,直到我设法理解它为什么会发生。在我删除了所有不必要的信息后,代码如下所示: let foo = 2; console.log(foo); if (foo === 2){ console.log(foo); let foo = 1; } 它在第5行抛出未定义的foo。当我尝试console.log(foo)时,会弹出一个错误!如果我删除第6行让foo=1代
x未定义
错误,这让我有点困惑,因为x
之前已经定义了几行。我不得不花一些时间调整我的代码,删除和添加行,直到我设法理解它为什么会发生。在我删除了所有不必要的信息后,代码如下所示:
let foo = 2;
console.log(foo);
if (foo === 2){
console.log(foo);
let foo = 1;
}
它在第5行抛出未定义的foo。当我尝试console.log(foo)
时,会弹出一个错误!如果我删除第6行让foo=1代码>代码工作正常。我的意思是在我第二次声明foo
之前发生了一个错误。因此,第一个问题是:
第6行(尚未执行)如何可能导致第5行出现错误
我不明白的第二件事是,为什么它说foo没有定义
,而不是foo已经声明了
。
如果我用var
替换第二个let
,第6行将出现一个错误,它会说foo已经声明了
,所以看起来很好。但是将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
语句之间的时间称为时间死区(TDZ),在此期间绑定存在,但未初始化,不能以任何方式使用。即使在代码流中遇到let foo
之前,只要在块中使用let foo
就可以对外部foo
进行阴影处理
除了作用域之外,var
和let
之间的最大区别在于var
创建绑定并将其初始化为未定义的
,而不管var
语句在作用域中的何处。相反,let
(和const
和class
)创建绑定,但在以后的代码逐步执行过程中遇到let
(const
,class
)时才对其进行初始化。不能使用未初始化的绑定
为什么会抛出不正确的错误
这是正确的。你可能会说它措词不当。:-)基本上,它说“你不能在这里使用foo
,它没有初始化。”在我看来,V8(Chrome、Chrome、Brave、新的基于Chrome的Edge和Node.js中的JavaScript引擎)当前的错误消息更清楚:
未捕获引用错误:在初始化之前无法访问“foo”
第6行(尚未执行)如何可能导致第5行出现错误
因为用let
、const
和class
声明的绑定范围(松散地称为“变量”)是整个块,而不仅仅是从声明它们的位置到块的末尾。代码进入块和执行let
语句之间的时间称为时间死区(TDZ),在此期间绑定存在,但未初始化,不能以任何方式使用。即使在代码流中遇到let foo
之前,只要在块中使用let foo
就可以对外部foo
进行阴影处理
除了作用域之外,var
和let
之间的最大区别在于var
创建绑定并将其初始化为未定义的
,而不管var
语句在作用域中的何处。相反,let
(和const
和class
)创建绑定,但在以后的代码逐步执行过程中遇到let
(const
,class
)时才对其进行初始化。不能使用未初始化的绑定
为什么会抛出不正确的错误
这是正确的。你可能会说它措词不当。:-)基本上,它说“你不能在这里使用foo
,它没有初始化。”在我看来,V8(Chrome、Chrome、Brave、新的基于Chrome的Edge和Node.js中的JavaScript引擎)当前的错误消息更清楚:
未捕获引用错误:在初始化之前无法访问“foo”
使用声明变量时,让它在当前代码块的范围内有效。您的第二个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
,则应在使用之前将其定义移动到
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