如果未悬挂let或它们进入了临时盲区,那么为什么此代码段可能会在使用全局引用时抛出错误?

问题描述

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

与用var声明的变量将以undefined值开头的变量不同,let变量在确定其定义之前不会被初始化。在初始化之前访问变量将导致ReferenceError。该变量从程序段的开始一直处在“临时死区”中,直到初始化完成为止。

该块的开头是开头{,而您的console.log(a)let语句之前,因此它位于此“死区”。

为什么这样工作?因为它可以帮助程序员检测由于不同作用域中具有相同名称的变量之间的混淆而导致的代码错误。

,

要添加到以上两个答案中,语句let a = 55实际上是两个语句合而为一:let a-一个声明-和a = 55-一个赋值。由于Java的吊装规则,声明在进入块时进行处理,但赋值保留其词法位置。

所以块:

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

在语义上等同于:

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

由于a的局部声明会掩盖同名的全局变量,因此在执行console.log(a)时,a已声明但尚未分配值。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...