Javascript ES6中let吊装的目的是什么?
我知道Javascript ES6中let吊装的目的是什么?,javascript,ecmascript-6,Javascript,Ecmascript 6,我知道let将被提升到块的顶部,但在初始化之前访问它将抛出ReferenceError,因为它处于暂时死区 例如: console.log(x); // Will throw Reference Error let x = 'some value'; 但这样的代码片段将不会出错: foo(); // alerts foo; function foo(){ // foo will be hoisted alert("foo"); } 我的问题 let被提升到顶部时会在访问时抛
let
将被提升到块的顶部,但在初始化之前访问它将抛出ReferenceError
,因为它处于暂时死区
例如:
console.log(x); // Will throw Reference Error
let x = 'some value';
但这样的代码片段将不会出错:
foo(); // alerts foo;
function foo(){ // foo will be hoisted
alert("foo");
}
我的问题
let
被提升到顶部时会在访问时抛出错误,其目的是什么?同样,var也会受到TDZ的影响,我知道它什么时候会抛出未定义的
变量是在其包含词法环境为
实例化,但在变量
已评估词典绑定。词汇表定义的变量
对于初始值设定项,将为其初始值设定项的
计算LexicalBinding时的AssignmentExpression,而不是在
变量被创建。如果let声明中的一个词典绑定
没有初始值设定项变量被赋予未定义的值
在对词典进行求值时
还包括:
let允许您声明在范围内受限于
用于其上的块、语句或表达式这与
var关键字,它全局定义变量,或局部定义变量
不考虑块范围的整个功能。
您也可以查看凯尔·辛普森的这篇文章:您必须首先了解吊装。将代码声明初始化为块的顶部,请考虑以下示例
function getValue(condition) {
if (condition) {
var value = "blue";
// other code
return value;
} else {
// value exists here with a value of undefined
return null;
}
// value exists here with a value of undefined
}
正如您所看到的,该值可以在else和function中访问。因为它直接在getValue(condition)函数之后声明
function getValue(condition) {
if (condition) {
let value = "blue";
// other code
return value;
} else {
// value doesn't exist here
return null;
}
// value doesn't exist here
}
但是当我们使用时,让你看到不同。这些例子摘自我正在阅读的一本书,推荐你也去看
进一步澄清用一种很好的方式解释了它,并提供了与该主题相关讨论的链接
解释这个问题的内容
为什么let
存在暂时死区
如果TDZ没有引起引用错误,并且您在变量声明之前(即在TDZ中)访问了变量,那么您(很可能)会错过一个编程错误。导致引用错误的TDZ可以帮助您捕获编程错误
因此,您的下一个问题是-为什么要为let
设置TDZ?为什么不在声明变量时启动let
变量的作用域?答案是const
。TDZ用于const
和(差)let
被TDZ卡住,只是为了更容易在let
和const
之间切换
var也会受到TDZ的影响,我知道它什么时候会抛出未定义的
但这是因为TDZ吗
否,var
不受TDZ影响。它不会抛出任何错误。它只是未定义的
,除非另行设置。TDZ是一个ES6东西。Alet
变量未被提升。说一个let
变量是“highed”在技术上是正确的,但我认为这个术语的使用是误导性的。描述语义的一种等效方法是,当您试图在其声明上方引用它时,会得到一个ReferenceError
,因为它还不存在;如果试图引用该块中任何地方都不存在的变量,也会得到同样的结果
更多信息:
C++和JavaScript都有块作用域,但在这一点上有所不同,所以我们可以通过了解它们的不同行为来理解这一点。考虑这个例子:
#include <iostream>
int main() {
int x = 3;
{
std::cout << x << std::endl;
int x = 4;
}
return 0;
}
在JavaScript中,通过“提升”第二个x
,解决了此问题,但使其在访问时抛出ReferenceError
。据我所知,这种“提升”相当于将对x的引用视为由于歧义而产生的错误,这是应该的
let
被提升到顶部时会在访问时抛出错误,其目的是什么
这样我们就可以有块范围,这是一个相当容易理解的概念,而不必有块等价物var
highting,这是一个传统的bug和误解的来源
考虑这一块的内部:
{
let a = 1;
console.log(a);
let b = 2;
console.log(a, b);
let c = 3;
console.log(a, b, c);
}
设计师在这里有三个主要选择:
具有块范围,但所有声明都挂到顶部并可访问(如var
处于函数中);或
没有块作用域,而是从每个let
、const
、类开始创建一个新作用域。;或
有块作用域,有提升(或者我称之为“半提升”),其中声明被提升,但是它们声明的标识符在代码中到达之前是不可访问的
选项1让我们面临着与var
相同的bug。选项2对于人们来说要理解要复杂得多,对于JavaScript引擎来说要做的工作也更多(如果您需要,请参阅下面的详细信息)。选项3达到了最佳效果:块范围很容易理解和实现,TDZ可以防止由var
引起的错误
另外,var
也会受到TDZ的影响,我知道它什么时候会抛出undefined
,但这是因为TDZ吗
否,var
声明没有TDZ<代码>未定义
不会被抛出,它只是一个变量在声明时的值,但没有设置为任何其他值<代码>变量
声明被提升到函数或全局环境的顶部,并在该范围内完全可访问,甚至在到达变量
行之前
这可能有助于理解JavaScript中如何处理标识符解析: 规范用一种叫做a的东西来定义它,它包含关于varia的信息
{
let a = 1;
console.log(a);
let b = 2;
console.log(a, b);
let c = 3;
console.log(a, b, c);
}
function example() {
console.log("alpha");
var a = 1;
let b = 2;
if (Math.random() < 0.5) {
console.log("beta");
let c = 3;
var d = 4;
console.log("gamma");
let e = 5;
console.log(a, b, c, d, e);
}
}