这是时间死区的工作原理吗?

时间:2018-06-18 03:03:05

标签: javascript

我一直在试图弄清楚letconst的时间死区/解析是如何工作的。这就是它似乎归结为(基于我在之前的问题[例如thisthis]中收到的文档和各种回复,尽管如果出现分歧,这会得到一些答案)。这个摘要是否正确?

在作用域的顶部,JS引擎在相关作用域的顶部创建一个绑定(变量关键字和名称的关联,例如let foo;),这被认为是提升变量,但是如果您尝试在声明位置之前访问变量,JS会抛出ReferenceError

一旦JS引擎向下移动到声明(与“定义”同义),例如let foo;,引擎就会初始化它(为它分配内存并使其可访问)。声明具有自我约束力。 (这是对我没有意义的部分:绑定导致顶部的提升,但是引擎在达到声明之前不会初始化,声明也具有绑定效果。)如果没有在undefined的情况下,变量的值设置为let,如果使用const,则会抛出SyntaxError

此处参考具体说明:

ECMAScript 2019语言规范草案:第13.3.1节,Let and Const Declarations

  

let和const声明定义作用域的变量   运行执行上下文的LexicalEnvironment。变量是   在实例化包含词法环境时创建但是   在变量的LexicalBinding之前,可能无法以任何方式访问它   评估。由带有初始化程序的LexicalBinding定义的变量   被赋值为Initializer的AssignmentExpression的值   评估LexicalBinding,而不是在创建变量时。如果   let声明中的LexicalBinding没有初始化器   当LexicalBinding为时,变量被赋值undefined   评价。

MDN网络文档:Let

  

让绑定在包含的(块)范围的顶部创建   声明,通常称为“吊装”。与变量不同   用var声明,它将以undefined值开头,let   在评估定义之前,不会初始化变量。   在初始化之前访问变量会导致a   引发ReferenceError。该变量位于“时间死区”   块的开始直到处理初始化。

2 个答案:

答案 0 :(得分:0)

TDZ的理解非常复杂,需要一篇博客文章来阐明其实际效果。 但实质上,过于简化的解释是

  

let / const声明会提升,但是在初始化之前访问时会抛出错误(而不是像var那样返回undefined)

我们来看这个例子

let x = 'outer scope';
(function() {
    console.log(x);
    let x = 'inner scope';
}());

由于TDZ语义,上面的代码将抛出一个ReferenceError。

所有这些都来自great article完全关于 TDZ 。 感谢作者。

答案 1 :(得分:0)

也许首先您需要了解TDZ存在的原因:因为它可以防止变量提升的常见惊人行为并修复潜在的错误来源。 E.g:

var foo = 'bar';

(function () {
    console.log(foo);
    var foo = 'baz';
})();

这是许多(新手)程序员经常出人意料的原因。 It's too late to change the behaviour of var now,因此ECMAScript小组决定至少通过引入letconst来修复行为。究竟是如何在幕后实施的是一个有点没有用的点,重要的是它能够阻止它最有可能成为一个错字/结构性错误:

let foo = 'bar';

(function () {
    console.log(foo);
    let foo = 'baz';
})();

实际上,Javascript是在两个步骤中执行的:

  1. 将代码解析为AST /可执行字节代码。
  2. 运行时执行。
  3. 解析器将在第一步中看到var / let / const声明,并将使用保留符号名称等设置范围。那是悬挂。在第二步中,代码将在该设置范围内起作用。显而易见的是,解析器/引擎可以在第一步中自由地执行任何操作,其中一项操作是在内部标记TDZ,这将在运行时引发错误。