如果 let 没有被提升或者它们进入了临时死区,那么为什么这个片段会抛出错误,而它本可以使用全局引用

If let is not hoisted or they goes in temporal dead zone, then why this snippet is throwing error, when it could have just used the global reference

var a = 6;
{
  console.log(a)
  let a =55
  
} 

当我执行此代码段时,我收到以下错误消息: ReferenceError: 初始化前无法访问 'a'

为什么 console.log(a) 没有给出 6 作为结果。

嵌套块将创建一个新的块作用域词法环境。

内部 a 变量在该范围内 声明,但在初始化之前访问,因此出现错误。

内部范围let a声明覆盖了var a声明,所以它是一个不同的变量,就好像你这样写:

var a = 6;
{
  console.log(a2)
  let a2 =55
  
} 

.

您的问题的答案在您的标题中:变量处于“时间死区”,这只是您所看到的行为的名称。

this explanation on MDN:

Unlike variables declared with var, which will start with the value undefined, let variables are not initialized until their definition is evaluated. Accessing the variable before the initialization results in a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.

块的开始是开头 { 并且你的 console.log(a) 出现在 let 语句之前,所以它在这个“死区”中。

为什么会这样?因为它可以帮助程序员检测代码中由于混淆不同范围内的同名变量而导致的错误。

为了补充以上两个答案,语句 let a = 55 实际上是两个语句合二为一:let a - 声明 - 和 a = 55 - 赋值。由于 Javascript 的提升规则,声明在进入块时处理,但赋值保留其词法位置。

所以块:

var a = 6
{
  console.log(a)
  let a = 55
} 

在语义上等同于:

var a = 6
{
    let a
    console.log(a)
    a = 55
}

因为a的局部声明屏蔽了同名的全局变量,所以到console.log(a)执行的时候a已经声明但是还没有赋值。