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

Why does this un-assigned let variable not cause a Reference Error?

为什么在此代码段中尝试访问 bar 不会导致引用错误?我读过试图解释 letvar 之间差异的问题/答案,但 none 似乎解释了顶部和底部示例的行为差异。

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 的引用错误。 "Well, duh, I'm trying to see if it is defined!"

我会声明 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

let 绑定在包含声明的(块)范围的顶部创建,通常称为 "hoisting"。与以 undefined 值开始的 var 声明的变量不同,let 变量在其定义被评估之前不会被初始化。在初始化之前访问变量会导致 ReferenceError。从块的开始到处理初始化,变量都在 "temporal dead zone" 中。

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

未分配并不意味着未初始化。 let bar; 语句与 let bar = undefined; 的作用相同 - 它以 undefined 作为默认值初始化,除非您在变量声明中提供显式初始化程序 ("right hand side")。

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');

有关时间死区的详细信息,请参阅