Chrome console 已经声明的变量为 let 抛出未定义的引用错误

Chrome console already declared variables throw undefined reference errors for 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

所以我不能使用 "let" 因为 a 已经声明了。所以我尝试将其他内容重新分配给 "already declared a"

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

跟进

"manually" 提升 let 语句与隐式大小写之间似乎有些区别。

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

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

let example
throw new Error
example = 5

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

解释为 let a; a = werwr;

这就是为什么当您 运行 您的第二行代码时 a 已经声明的原因。

更新

所以,在 ES 规范中有一个 NOTE https://tc39.github.io/ecma262/#prod-LetOrConst

let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer's AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when the LexicalBinding is evaluated.

...

"but may not be accessed in any way until the variable's LexicalBinding is evaluated" 意味着,必须成功完成声明才能访问变量(获取值、赋值或执行 typeof,或事件 delete);

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

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

请关注 link 并阅读更多相关信息。如果您找到恢复变量 a 的方法,请告诉我。 谢谢,今天我发现了一些关于 Javascript.

的新东西

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

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 控制台中遇到同样的问题有点麻烦,但可以将控制台作为特殊范围解决。