为什么在有TDZ时提升变量

时间:2016-01-22 10:14:41

标签: javascript lexical-scope

ES6标准提出了Temporal Dead Zones,在评估词法绑定之前,无法以任何方式进行变量引用。那么词汇环境初始化时的变量创建意味着什么呢?

  1. 程序员?
  2. 编译器?
  3. 使用var声明声明变量可能对程序员以前有意义,但是现在有了TDZ,为此目的,javascript开始表现得像java吗?除了javascript解释器的工作方式之外,还有什么理由我们首先提升(因此是TDZ)吗?

    如果代码后面因为执行顺序遇到词法绑定,即使代码在词法之前出现,会发生什么?

    let abc = f();
    let b;
    f(){ return b;}
    

    像java这样的传统编程语言何时创建变量?遇到变量声明时?或者当词汇范围初始化时?

2 个答案:

答案 0 :(得分:1)

  

那么词汇环境下的变量创建是什么呢?   初始化对程序员意味着什么?

不多。程序员只打算使用声明和初始化变量。

变量在整个范围内可用(从头开始)只意味着错误会更容易被捕获,因为在初始化之前使用变量失败(有例外)而不是默默地解析为外部错误范围(全局?)变量。它还意味着标识符,无论在何处使用,都始终引用局部变量 - 这正是我们对范围的期望。

  

那么词汇环境下的变量创建是什么呢?   初始化对编译器意味着什么?

词汇环境在执行过程中不会改变其结构。已知范围内的标识符的静态解析使编译成为可能,并且执行速度更快。

就像反例一样,考虑一下这个问题:

var x = "global";
var code = "var x = 'local';";
(function() {
     "use sloppy";
     function test() {
         console.log(x); // what do you think does `x` refer to?
     }                   // It's hard to understand as a developer,
                         // now imagine being a compiler that tries to optimise `test`.
     test();
     eval(code);
     test();
}());
  

稍后在代码中遇到词法绑定时会发生什么   由于执行的顺序,即使代码在词法之前出现?

b初始化之前调用{p> f()。访问它会引发TDZ异常 You can try it online

答案 1 :(得分:1)

我有一种感觉,TDZ的创建与var是一个非常卑鄙的步骤有关,而如果他们采用看似更合乎逻辑的方法甚至没有标识符存在,引擎就会有进行更加密集的变革。至于你的问题的第二部分,参考其他语言"创建"变量,还有许多其他重要因素需要考虑,你似乎已经遗漏了,比如语言被解释和编译,以及有多个不同的步骤来创建"一个变量。它在许多不同的情况下表现不同,并没有单一的答案。事实上,这是存在许多不同语言的重要原因之一。

至于你的编码问题,这取决于你何时调用你的f函数,因为函数声明是在javascript中提升的。如果您在声明b之前调用它,那么您在TDZ中并且无法引用b。它的行为非常相似,就好像只是在调用此函数的地方放置return b一样。

老实说,似乎对javascript和计算机语言存在一些潜在的误解。 Javascript不是"表现"更像是java,实际上新的let关键字具有非常细微的行为,例如,与java中的类型/变量声明相比,能够成为块作用域。我建议不要试图用其他语言来考虑ES6的变化; javascript与许多其他语言不同,如果你这样做,将很难理解这些概念以及如何使用javascript进行编程。

编辑:

至于为什么存在变量和函数声明提升,即easily googlable.