让我们在ES6中吊装的目的是什么?

时间:2016-02-24 09:20:33

标签: javascript ecmascript-6

我了解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?

4 个答案:

答案 0 :(得分:4)

documentation说:

  

变量是在包含词法环境时创建的   实例化但在变量之前可能无法以任何方式访问   评估LexicalBinding 。由LexicalBinding定义的变量   为初始化程序分配其初始化程序的值   评估LexicalBinding时的AssignmentExpression,而不是何时   变量已创建。如果let声明中的LexicalBinding有   没有初始化程序,变量被赋值undefined   在评估LexicalBinding时。

var keyword

  

允许您声明范围有限的变量   使用它的块,语句或表达式。 这与此不同   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存在暂时死区?

  1. 如果TDZ没有引起参考错误,并且在声明之前(即在TDZ中)访问了变量,则(很可能)会错过编程错误。导致参考错误的TDZ可以帮助您解决编程错误。

  2. 所以你的下一个问题是 - 为什么甚至有let 的TDZ?为什么不在声明它时启动let变量的范围?答案是const。 TDZ适用于const而(差)let仅限于使用TDZ,以便更轻松地在letconst之间切换

  3.   

    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错误,应该如此。