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

Javascript Chrome控制台已声明的变量为let抛出未定义的引用错误,javascript,scope,ecmascript-6,google-chrome-devtools,let,Javascript,Scope,Ecmascript 6,Google Chrome Devtools,Let,最近我在chrome控制台上遇到了这个奇怪的东西。在这里,我故意将一个未定义的东西分配给,以便抛出一个错误 let a = werwr // Uncaught ReferenceError: werwr is not defined 然后,当我试图将合法的东西分配给a时,发生了这样的情况: let a = "legit string" // Uncaught SyntaxError: Identifier 'a' has already been declared 所以我不能使用“let

最近我在chrome控制台上遇到了这个奇怪的东西。在这里,我故意将一个未定义的东西分配给,以便抛出一个错误

let a = werwr // Uncaught ReferenceError: werwr is not defined
然后,当我试图将合法的东西分配给a时,发生了这样的情况:

let a = "legit string"   // Uncaught SyntaxError: Identifier 'a' has already been declared
所以我不能使用“let”,因为已经声明了。所以我试着给“已声明的a”重新分配一些其他内容

因此,似乎我无法将其他内容重新分配给a,但同时,a已声明,因此我无法再次使用let

我理解声明变量和赋值变量之间的区别。然而,在这里,这两件事似乎都不能再做了。这是否与控制台中“let”的范围有关?因为同样的东西完全适用于“var”

跟进

“手动”提升let语句和隐式语句之间似乎有一些区别

throw new Error
let example = 5
// same errors as before
而在本例中,可以重新分配示例

let example
throw new Error
example = 5

您应该了解JS中的吊装。基本上,像这样的声明
设a=werwr

被解释为

让我们一起来;
a=werwr

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

更新

因此,ES规范中有一个注释

让和const声明定义作用域为 正在运行执行上下文的词典环境。变量是 在实例化其包含词汇的环境时创建 在变量的字典绑定完成之前,不能以任何方式访问 评估。由具有初始值设定项的词典定义的变量 在以下情况下为其初始值设定项的AssignmentExpression赋值: 在创建变量时,不会计算LexicalBinding。如果 let声明中的词典绑定没有初始值设定项 该变量被指定为未定义的值 进行了评估

“但在对变量的LexicalBinding求值之前,不能以任何方式访问” 意味着,在访问变量(获取值、赋值或执行
typeof
,或事件
delete
)之前,必须成功完成声明

在您的例子中,变量的字典绑定被异常中断

let a = werwr // Uncaught ReferenceError: werwr is not defined
请点击链接并阅读更多相关信息。如果你想办法恢复变量
a
,请告诉我。
谢谢,今天我发现了一些关于Javascript的新东西。

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

function …() {
    if (false)
        example; // would throw a ReferenceError if it was evaluated
    … // do something
    if (true)
        return; // stop!
    let example = 5; // never executed
}
这在函数范围内是可以的。可能出了问题,可能根本不需要变量-在下一次调用中,将创建一个包含新变量的新范围

在全局范围中也可能发生类似的情况,当您在初始化变量之前抛出异常时(这里只有异常作为控制流构造工作,其他任何情况都无法达到相同的效果)

与函数作用域相反,变量保持未初始化状态在这里很重要。全局范围将永远存在,变量将永远处于死区。它没有也永远不会被初始化,词法变量不能被重新声明(这有助于防止错误)

这一点,但被认为无关紧要。如果顶级
执行抛出错误,则您的问题比未初始化的变量更大。没有恢复的途径。如果您需要一个(例如,通过尝试在连续脚本中重新声明),您必须使用
var


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

@JaromandaX修复了拼写错误,例如chrome中的控制台在一开始就处于严格模式-firefox中存在类似的问题,除了
a=“legit string”
每次都会起作用,这在chrome控制台中似乎是一个麻烦,这是肯定的-但是,这不会对网页产生任何影响all@JaromandaX谢谢,只是好奇而已。如果发生这种情况,我每次都得刷新一下,这有点烦人。由于这些错误,我不可能再次重新定义a。如果是这样,我应该能够执行“a=”合法字符串,但它抛出了未定义的错误。另外,如果我像你一样单独写陈述,我可以重新分配a。然而,在我的例子中,这并没有发生。你是对的,我最后的解释是Chrome开发者工具通过eval()运行你的脚本。我正试图以此为例。但是,使用
在eval()中。。。。好。祝你好运,谢谢你的研究。如果你有兴趣的话,Bergi的回答非常彻底考虑到let被提升,我写了这样的代码:“let x;抛出新错误;x=6”在这种情况下,x实际上可以在以后重新分配。“手动”提升声明语句和隐式实现之间有什么细微的区别吗?我用更好的格式补充了问题的后续内容是的,
let x
的快捷方式,让x=未定义,如果您手动将其放在顶部,您将在引发异常之前初始化变量。Re“没有可恢复的路径”,将来它可能能够
@Pacerier您可以处理错误(今天已使用
window.onerror
)并记录错误,但您无法恢复它。在抛出异常之前,不可能撤消脚本所做的操作,也不可能取消声明变量。
let a = werwr // Uncaught ReferenceError: werwr is not defined
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;