javascript - 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。
解决方案
重要区别之一:
不同之处在于var studentName 自动在作用域的顶部初始化,而 let studentName 不会。
您的问题中的示例片段未说明,因为您不会尝试在声明变量let
之前访问它们。
在上面的例子中,第二个 studentName 声明基本上是一个空操作,因为 studentName 已经被声明了。但这与 let 示例有何关系?
使用let
, 不允许重新声明 - 相反,代码中必须有一条语句,可以确定变量名称超出时间死区并被代码的其他部分引用。直到一个变量被完全初始化——也就是说,直到解释器跑过这let someVarName
条线(不管是否给它分配了东西=
)——变量名不能被分配或检索。
除此之外,let someVarName
非常类似于var someVarName
-将在那个时刻为变量let
分配一个值,并且 将在作用域的开头给变量一个值。undefined
var
undefined
“不同之处在于 var studentName 自动在范围顶部初始化,而 let studentName 不会。” 我不确定这意味着什么,因为我一直认为如果在声明时没有指定值,let 会自动初始化为 undefined
请参阅此示例:
// Not permitted:
console.log(studentName); // Error
let studentName;
相比于:
// OK
console.log(studentName);
var studentName;
使用let
,在解释器运行完成之前,您无法引用所述变量let someVarName
。
推荐阅读
- configuration - 在应用模块导入模块之前加载配置文件
- eclipse - 在eclipse上将maven项目转换为clojure项目
- temp-tables - 使用 CTAS 创建 Azure SQL 数据仓库临时表导致意外的行顺序
- php - 通过属性 ID 获取 WooCommerce 属性缩略图 URL(WooCommerce 产品搜索插件)
- javascript - javascript -> webdriver.io 中的 getAttribute
- c# - 是否可以生成带有自动填写字段的共享点调查链接?
- java - IntelliJ IDEA 在重新打开/重新启动项目后自动删除 Gradle 模块
- abap - 设置参数 ID 不适用于自定义屏幕
- angularjs - ng-show(或 ng-class)不适用于 iPhone 的 Safari iO 上的 ui-view
- plotly.js - 当它遇到图表顶部时不显示绘图跟踪