我了解let
将被提升到块的顶部,但在初始化之前访问它会因ReferenceError
Temporal Dead Zone
例如:
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的影响,我知道什么时候它会抛出undefined
,但这是因为TDZ?
答案 0 :(得分:4)
变量是在包含词法环境时创建的 实例化但在变量之前可能无法以任何方式访问 评估LexicalBinding 。由LexicalBinding定义的变量 为初始化程序分配其初始化程序的值 评估LexicalBinding时的AssignmentExpression,而不是何时 变量已创建。如果let声明中的LexicalBinding有 没有初始化程序,变量被赋值undefined 在评估LexicalBinding时。
允许您声明范围有限的变量 使用它的块,语句或表达式。 这与此不同 var关键字,它全局定义变量,或者本地定义变量 整个功能,无论块范围如何。
您还可以查看Kyle Simpson的这篇文章:For and against let
答案 1 :(得分:1)
http://www.2ality.com/2015/10/why-tdz.html以一种很好的方式解释它,并链接到https://mail.mozilla.org/pipermail/es-discuss/2012-September/024996.html,这是关于该主题的相关讨论。
解释此问题的内容
为什么
let
存在暂时死区?
如果TDZ没有引起参考错误,并且在声明之前(即在TDZ中)访问了变量,则(很可能)会错过编程错误。导致参考错误的TDZ可以帮助您解决编程错误。
所以你的下一个问题是 - 为什么甚至有let
的TDZ?为什么不在声明它时启动let
变量的范围?答案是const
。 TDZ适用于const
而(差)let
仅限于使用TDZ,以便更轻松地在let
和const
之间切换
var也会受到TDZ的影响,我知道什么时候会抛出未定义的 但这是因为TDZ?
不,var
不会受到TDZ的影响。它不会抛出任何错误。它只是undefined
,否则设置。 TDZ是ES6的一部分。
答案 2 :(得分:0)
你必须先了解吊装。这是将代码声明初始化到块的顶部,请考虑以下示例
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和函数中访问该值。因为它在getValue(条件)函数之后被直接声明。
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
}
但是当我们使用时,你可以看到差异。这些例子来自我正在阅读的一本书,建议你也看看
https://leanpub.com/understandinges6/read#leanpub-auto-var-declarations-and-hoisting
进一步澄清
答案 3 :(得分:-1)
说let
变量未被提升。let
变量'悬挂'在技术上是正确的,但在我看来,这个术语的使用具有误导性。描述语义的一种等效方法是当你试图在它的声明之上引用它时得到ReferenceError
,因为它还不存在;如果你试图引用那个块中不存在的变量,你会得到同样的东西。
更多信息:
C ++和JavaScript都有块范围,但在这个特定点上有所不同,所以我们可以通过理解它们的行为方式来理解这一点。考虑这个例子:
#include <iostream>
int main() {
int x = 3;
{
std::cout << x << std::endl;
int x = 4;
}
return 0;
}
在C ++中确实没有提升,当x
行运行(将cout
打印到屏幕上)时,第二个x
不存在,但是第一个{{1}仍然如此,所以程序乖乖地打印3.这很令人困惑。我们应该考虑对x
的引用含糊不清并使其成为错误。
这是在类似的JavaScript代码中发生的事情:
x
在JavaScript中,此问题已通过“提升”第二个'use strict';
let x = 3;
(() => {
console.log(x);
let x = 4;
})();
来解决,但在访问时会使其x
。据我所知,这种“提升”相当于由于模糊性而引用ReferenceError
错误,应该如此。