问题描述
最近我在Chrome控制台遇到了这个奇怪的事情。在这里,我故意为a抛出一个未定义的东西,以便抛出错误。
Recently I ran into this weird thing in chrome console. Here I am intentionally assigning an undefined thing to a in order to throw an error.
let a = werwr // Uncaught ReferenceError: werwr is not defined
然后,当我尝试为a分配合法的内容时,发生了这种情况:
Then when I tried to assign something legit to a, this happened:
let a = "legit string" // Uncaught SyntaxError: Identifier 'a' has already been declared
所以我不能使用let,因为已经声明了a。所以我试图将其他东西重新分配给已经宣布为
so I can't use "let" because a has already been declared. So I tried to reassign something else to the "already declared a"
a = "legit string" // Uncaught ReferenceError: a is not defined
所以我似乎无法将其他内容重新分配给a但同时,a已经宣布,所以我再也不能使用了。
So it seems like I can't reassign something else to a but at the same time, a has been declared so I can't use let again.
我理解声明和赋值变量之间的区别。但是在这里似乎不能再做了。这是否与控制台中let的范围有关?因为同样的事情完全适用于var
I understand the difference between declaring and assigning a variable. However here it seems that neither could be done again. Does this has something to do with the scope of "let" in console? Because the same thing totally works for "var"
var a = werwr
// Uncaught ReferenceError: werwr is not defined
a = "legit string"
// "legit string"
var a = "legit string"
// Uncaught SyntaxError: Identifier 'a' has already been declared
后续行动
手动挂起let语句与隐含情况之间似乎有一些区别。
There seem to be some difference between "manually" hoisting the let statement vs the implicit case.
throw new Error
let example = 5
// same errors as before
虽然在这种情况下可以再次重新分配示例。
while in this case example can be reassigned again.
let example
throw new Error
example = 5
推荐答案
当您引入时间死亡时会发生这种情况区域到全球范围。您可能知道,让
声明。由于控制流,可能会发生变量从未初始化:
This happens when you introduce the temporal dead zone to the global scope. As you might know, let
declarations are hoisted but left uninitialised. Due to control flow, it can happen that a variable is never initialised:
function …() {
if (false)
example; // would throw a ReferenceError if it was evaluated
… // do something
if (true)
return; // stop!
let example = 5; // never executed
}
在函数范围内这很好。可能出现了问题,也许根本不需要变量 - 在下一次调用中,将创建一个带有新变量的新范围。
This is fine in a function scope. Maybe something went wrong, maybe the variable wasn't needed at all - in the next call, a new scope with a new variable will be created.
类似的事情可以发生在全局范围内,当你在变量初始化之前抛出异常时(这里只有异常作为控制流构造工作,没有其他任何东西可以达到相同的效果)。
A similar thing can happen in the global scope, when you throw an exception before the variable is initialised (only exceptions work here as a control flow construct, nothing else achieves the same effect).
throw new Error;
let example = 5;
与函数范围相比,此变量保持未初始化非常重要。全局范围永远持续,变量永远死亡。它不会也不会被初始化,并且词法变量不能被重新声明(这有助于防止错误)。
In contrast to the function scope, it does matter here that the variable stays uninitialised. The global scope lasts forever, and the variable is eternally dead. It was not and will never be initialised, and lexical variables cannot be re-declared (which helps preventing mistakes).
这,但被视为无关紧要。如果顶级< script>
执行会抛出错误,则问题比未初始化的变量更大。没有恢复的途径。如果你需要一个(例如通过尝试在连续的脚本中重新声明它),你必须使用 var
。
This was discussed on es-discuss, but deemed irrelevant. If top-level <script>
execution throws an error, you have bigger problems than uninitialised variables. There is no path to recover. If you need one (e.g. by trying to re-declare it in successive scripts), you have to use var
anyway.
你在devtools控制台中遇到同样的问题有点令人讨厌,但可以作为特殊范围的控制台解决。
That you have the same problem in the devtools console is a bit of a nuisance, but could be solved for the console as a special scope.
这篇关于Chrome控制台已声明变量为let发出未定义的引用错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!