首页 > 解决方案 > JS - `let` 与 `var` 的自动初始化行为

问题描述

在“You Don't Know JS Yet”的“Chapter 5: The (Not So) Secret Lifecycle of Variables”中,标题为“Uninitialized Variables (aka, TDZ)”的部分说,初始化未初始化let变量的唯一方法是使用附加到声明语句的赋值(因为赋值本身是不够的)。以下示例说明了这一点。

示例 1:

let studentName = "Suzy";
console.log(studentName);   // Suzy

在下一个示例中,声明和初始化是分开的——let变量在第 1 行声明,然后在第 2 行初始化:

示例 2:

let studentName;
// or:
// let studentName = undefined;
    
studentName = "Suzy";

console.log(studentName);
// Suzy

在此示例下,有一个标注如下:

那很有意思!回想一下前面,我们说var studentName; 不一样var studentName = undefined;,但是在这里let,它们的行为是相同的。不同之处在于 var studentName 在范围的顶部自动初始化,而 let studentName 不会。

问题一:

我不确定上面的示例 2 如何证明这一点let studentName;并且let studentName = undefined;是等效的。在本章前面,标题为“重新声明?”的部分 用下面的例子来说明var studentName;不一样var studentName = undefined;

示例 3:

var studentName = "Frank";
console.log(studentName); // Frank

var studentName;
console.log(studentName); // Frank <--- still!

// let's add the initialization explicitly
var studentName = undefined;
console.log(studentName); // undefined <--- see!?

在上面的例子中,第二个studentName声明基本上是一个空操作,因为studentName已经被声明了。但这与let示例(示例 2)有何关系?即示例 2 如何显示let studentName;let studentName = undefined;表现相同?

问题2:

上面标注的第二句话说,“不同之处在于var studentName自动初始化在作用域的顶部,而let studentName没有。” 但是如果在声明时没有指定值,是否不会let自动初始化undefined(见这里)?

编辑:

我的错 - 关于问题 2,标注的第二句话确实有道理。规范说,如果一个声明let没有初始化表达式,那么当该let声明被评估时,那个 let-declared 变量将被分配一个 undefined 值。而如果var在没有初始化器的情况下进行声明,则该 var 声明的变量将在创建undefined时分配(请参阅 参考资料)。

但是,我仍然不确定问题 1。

标签: javascriptscopevariable-declarationhoistingvariable-initialization

解决方案


重要区别之一:

不同之处在于var studentName 自动在作用域的顶部初始化,而 let studentName 不会。

您的问题中的示例片段未说明,因为您不会尝试在声明变量let之前访问它们。

在上面的例子中,第二个 studentName 声明基本上是一个空操作,因为 studentName 已经被声明了。但这与 let 示例有何关系?

使用let, 不允许重新声明 - 相反,代码中必须有一条语句,可以确定变量名称超出时间死区并被代码的其他部分引用。直到一个变量被完全初始化——也就是说,直到解释器跑过这let someVarName条线(不管是否给它分配了东西=)——变量名不能被分配或检索。

除此之外,let someVarName非常类似于var someVarName-将在那个时刻为变量let分配一个值,并且 将在作用域的开头给变量一个值。undefinedvarundefined

“不同之处在于 var studentName 自动在范围顶部初始化,而 let studentName 不会。” 我不确定这意味着什么,因为我一直认为如果在声明时没有指定值,let 会自动初始化为 undefined

请参阅此示例:

// Not permitted:
console.log(studentName); // Error
let studentName;

相比于:

// OK
console.log(studentName);
var studentName;

使用let,在解释器运行完成之前,您无法引用所述变量let someVarName


推荐阅读