Chrome控制台已声明变量为let发出未定义的引用错误

时间:2016-12-21 04:26:09

标签: javascript scope ecmascript-6 google-chrome-devtools let

最近我在Chrome控制台遇到了这个奇怪的事情。在这里,我故意为a分配一个未定义的东西,以便抛出错误。

let a = werwr // Uncaught ReferenceError: werwr is not defined

然后,当我尝试为a分配合法的东西时,发生了这种情况:

let a = "legit string"   // Uncaught SyntaxError: Identifier 'a' has already been declared

因此我无法使用"让"因为已经宣布了。因此,我尝试将其他内容重新分配给"已经宣布为"

a = "legit string"   //  Uncaught ReferenceError: a is not defined

所以似乎我无法将其他内容重新分配给a,但与此同时,a已经宣布,所以我无法再次使用let。

我理解声明和赋值变量之间的区别。但是在这里似乎不能再做了。这是否与" let"的范围有关?在控制台?因为同样的事情完全适用于" 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语句与隐式案例挂起。

throw new Error
let example = 5
// same errors as before

虽然在这种情况下可以再次重新分配示例。

let example
throw new Error
example = 5

2 个答案:

答案 0 :(得分:9)

当您将时间死区引入全局范围时会发生这种情况。如您所知,let声明are hoisted but left uninitialised。由于控制流,可能会发生变量从未初始化:

function …() {
    if (false)
        example; // would throw a ReferenceError if it was evaluated
    … // do something
    if (true)
        return; // stop!
    let example = 5; // never executed
}

在功能范围内这很好。也许出了点问题,可能根本不需要变量 - 在下一次调用中,将创建一个带有新变量的新范围。

在初始化变量之前抛出异常时,全局范围内可能会发生类似的事情(只有异常在这里作为控制流构造工作,没有其他方法可以达到相同的效果)。

throw new Error;
let example = 5;

与功能范围相反,此处变量保持未初始化非常重要。全局范围永远持续,变量永远死亡。它不会也不会被初始化,并且不能重新声明词法变量(这有助于防止错误)。

was discussed on es-discuss,但被视为无关紧要。如果顶级<script>执行引发错误,则比未初始化的变量存在更大的问题。没有恢复的途径。如果你需要一个(例如,尝试在连续的脚本中重新声明它),你必须使用var

你在devtools控制台中遇到同样的问题有点麻烦,但可以作为特殊范围的控制台解决。

答案 1 :(得分:1)

你应该知道在JS中提升。基本上,这样的声明 let a = werwr;

被解释为 let a; a = werwr;

这就是为什么在运行第二行代码时已经声明了。

<强>更新

因此,ES规范中有一个注释 https://tc39.github.io/ecma262/#prod-LetOrConst

  

let和const声明定义作用域的变量   运行执行上下文的LexicalEnvironment。变量是   当他们包含的词汇环境被实例化时创建但是   在变量的LexicalBinding之前,可能无法以任何方式访问   评价即可。由带有初始化程序的LexicalBinding定义的变量   被赋予其初始化程序的AssignmentExpression的值   评估LexicalBinding,而不是在创建变量时。如果   let声明中的LexicalBinding没有Initializer   在LexicalBinding中为变量赋值undefined   被评估。

...

&#34;但在评估变量&#34;&#34; 之前,可能无法以任何方式访问它 意味着,必须先成功完成声明才能访问变量(获取值,赋值,或执行typeof或事件delete);

在您的情况下,变量的LexicalBinding会被异常中断。

let a = werwr // Uncaught ReferenceError: werwr is not defined

请点击链接,了解更多相关信息。如果您找到了恢复变通a的方法,请告诉我。 谢谢,今天我发现了一些关于Javascript的新内容。