【问题标题】:Why does this un-assigned let variable not cause a Reference Error?为什么这个未赋值的 let 变量不会导致引用错误?
【发布时间】:2018-07-20 22:20:41
【问题描述】:

为什么在这个 sn-p 中尝试访问 bar 不会导致引用错误?我已经阅读了试图解释 letvar 之间区别的问题/答案,但似乎没有一个可以解释顶部和底部示例的行为差异。

var foo;
let bar;

if( foo ) ()=>{}; // I expected this to be fine
if( bar ) ()=>{}; // I expected this to throw a reference error

console.log('finished');

(请随意回答这个问题,我的人生故事以及我为什么在下面提问)

我一直在努力改掉过度使用var 的坏习惯。在编写一些新代码时,我遇到了一个我以前从未见过的问题:使用if( myValue ) { ... } 会为未定义 myValue 引发引用错误。 “嗯,呵呵,我试试看有没有定义!”

我会声明myValue,并且在整个函数过程中,我可以为其赋值。在函数接近尾声时,我检查它是否有值,如果有,将执行一些额外的操作。

我记得在阅读有关 letvar 的文章时,var 基本上就像您在范围顶部为您的价值创建了容器一样,而我认为它会在您声明它的时间,但似乎在您分配它时这样做。所以,我可以使用var myValue;let myValue = undefinedif( typeof myValue !== 'undefined' ) { .. }。我知道最后一个是确保此类事情不再发生的最佳选择,即使它很丑陋。

然后,我写了上面的小sn-p来向同事解释这个错误......并且它起作用了?!?我试图弄清楚我可能错过的到底发生了什么,因为我想确切地了解哪里出了问题并从中吸取教训。但我现在真的很摸不着头脑,如果我不是更早的话,因为我认为我不仅发现了问题,而且解决了它……只是发现它可能只是一些无关紧要的事情。

附带说明:我的代码确实用一个let 声明了多个变量,它们之间使用逗号。这可能是一个因素吗?我确实多次重新阅读了这些声明,它们的格式都正确:

let value1 = 3,
    value2,
    value3 = 982,
    // ...
    myValue; // Add ` = undefined` to stop the Reference Error

// ...

if( myValue ) { /* ... */ } // Reference Error thrown here

【问题讨论】:

  • 不读取任何文本:未初始化的变量被初始化为undefined。换句话说,let x = undefined;let x; 是相同的(不包括异常情况)
  • @ASDFGerte 看来我遇到了某种怪异的情况。在我的底部示例中是否有任何可能指向这些异常案例之一的方向?底部是添加x = undefined 而不是仅仅声明 x 解决了参考错误问题,顶部问题的示例是我写的 sn-p 以显示原始问题是什么,并且没有我的行为预计基于问题的解决方案。
  • 我想到的案例并不是偶然发生的,我不知道有什么可以立即解释你的行为。我最好的猜测是您的列表中有一个分号:let value1 = 3; myValue;。代码将另外处于非严格模式,并且您不小心对全局变量进行了操作。
  • @ASDFGerte 我也曾寻找过。我看到的唯一可能奇怪的是分配给布尔表达式结果的变量,所以我在布尔表达式周围添加了一些括号,以确保我没有操作顺序问题,但没有发现任何区别。但是,如果是这种情况,变量不会抛出引用错误吗,因为它现在是全局 var 而不是 let 并且默认为 undefined?

标签: javascript referenceerror


【解决方案1】:

let 绑定在包含声明的(块)范围的顶部创建,通常称为“提升”。与用 var 声明的变量不同,它以 undefined 值开头,let 变量在其定义被评估之前不会被初始化。在初始化之前访问变量会导致 ReferenceError。从块开始到处理初始化,变量处于“临时死区”中。

更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

【讨论】:

  • 不过,这不是我所经历的。我期待一个参考错误,但没有得到一个。我认为这是我遇到的问题的原因,但是当我编写这个快速的 sn-p 来测试/显示这是原因时,它可以正常工作。
  • 哦,现在我明白了。您的情况似乎有点奇怪,我猜测其余代码中还有其他内容。所以真的,你的问题是在声明单个变量或逗号分隔的变量列表时是否存在行为差异。演示:link
  • 你是对的,我在使用单个 let 声明/初始化的其他变量中发现了一个放错位置的分号。我仍然对这个变量如何没有在我认为我声明它的地方引发引用错误感到困惑,因为它基本上是在做我的底部示例对第一个变量之一使用分号而不是逗号所做的事情。 ..所有具有默认值的变量都被提升了,但最后一个看起来应该是一个引用错误,因为它只是调用了一个未声明的变量并且什么都不做。
  • 我还在摸不着头脑,但听起来我的问题已经解决了!我在一个死区,只是觉得我不是。
【解决方案2】:

未分配并不意味着未初始化。 let bar; 语句与 let bar = undefined; 的作用相同 - 它使用 undefined 作为默认值进行初始化,除非您在变量声明中提供显式初始化程序(“右手边”)。

let 声明的变量在初始化之前访问它们时会抛出一个引用错误,当它们的声明语句被评估时:

let bar; // = undefined;

if (bar) {} // this is fine

console.log('finished');

if (bar) {} // this throws a reference error

let bar; // = undefined;

console.log('finished');

请参阅this topic 了解有关时间死区的更多详细信息。

【讨论】:

    猜你喜欢
    • 2020-04-26
    • 1970-01-01
    • 2021-03-10
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    • 2018-01-13
    • 1970-01-01
    相关资源
    最近更新 更多