为什么这个未分配的let变量不会导致引用错误?

时间:2018-07-20 22:20:42

标签: javascript referenceerror

为什么在此代码段中尝试访问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' ) { .. }。我认为最后一个是最好的选择,即使这种事情很难对付,也要确保这种事情不会再次发生。

然后,我写了上面的小片段向同事解释该错误...并且有效吗?我试图弄清楚我可能错过了什么,因为我想确切地了解出了什么问题并从中学习。但是,如果我不早的话,我现在真的要挠头了,因为我认为我不仅解决了问题,而且解决了这个问题……只是发现它可能与切线相关。 >

作为旁注:我的代码确实用一个let声明了多个变量,并在它们之间使用了逗号。这可能是一个因素吗?我确实多次阅读了这些声明,并且它们的格式都正确:

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

// ...

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

2 个答案:

答案 0 :(得分:2)

let绑定在包含声明的(块)作用域的顶部创建,通常称为“提升”。与以var声明的变量将以undefined值开头的变量不同,let变量要在对其定义求值后才进行初始化。在初始化之前访问变量会导致ReferenceError。该变量从块的开始一直处在“临时死区”中,直到进行初始化为止。

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

答案 1 :(得分:1)

未分配的并不意味着未初始化。 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