有TDZ为什么要提升变量

Why hoist variables when there is TDZ

ES6 标准提出了临时死区,使得在评估词法绑定之前不可能以任何方式进行变量引用。那么词法环境初始化时的变量创建意味着什么

  1. 程序员 ?
  2. 编译器 ?

使用 var 声明的变量声明以前可能对程序员有意义,但现在有了 TDZ,java 脚本是否开始像 java 那样运行?除了 javascript 解释器的工作方式之外,我们首先进行提升(结果是 TDZ)还有什么原因吗?

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

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

java 等传统编程语言何时创建变量?什么时候遇到变量声明?或者当词法作用域被初始化时?

So what does variable creation at the time of lexical environment initialisation mean to the programmer?

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

变量在整个范围内(从一开始)可用只意味着错误会更容易被发现,因为在初始化之前变量的使用失败(有一个例外)而不是默默地被解析为一个outer-scope(全局?)变量。这也意味着标识符,无论它在作用域中的什么地方被使用,总是引用局部变量——这正是我们对作用域的期望。

So what does variable creation at the time of lexical environment initialisation mean to the Compiler?

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

作为反例,考虑这个东西:

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();
}());

What happens when a lexical binding is encountered later in the code due to order of execution even when the code appears before it lexically?

b 在初始化之前由对 f() 的调用使用。访问它会引发 TDZ 异常。
You can try it online.

我有一种感觉,TDZ 的创建与 var 的一个非常卑微的步骤有关,而如果他们采用看似更合乎逻辑的方法,甚至不存在标识符,引擎将不得不经历更剧烈的变化。至于你的问题的第二部分,当其他语言 "create" 变量时,还有许多其他重要因素需要考虑,你似乎已经遗漏了,例如语言是解释还是编译,以及有是 "creating" 一个变量的多个不同步骤。它在许多不同的情况下表现不同,并且没有单一的答案。事实上,这是存在许多不同语言的重要原因之一。

至于您的编码问题,这取决于您何时调用 f 函数,因为函数声明是在 java 脚本中提升的。如果您在声明 b 之前调用它,那么您处于 TDZ 中并且无法引用 b。它的行为非常类似于您只是将 return b 放在调用此函数的任何地方。

老实说,似乎对 javascript 和一般的计算机语言存在一些潜在的误解。 Javascript 不是 "behaving" 更像 java,事实上,新的 let 关键字具有非常细微的行为,例如与 [=30= 相比,可以是块作用域] java 中的声明。我建议不要试图从其他语言的角度来考虑 ES6 的变化; javascript 与许多其他语言不同,理解这些概念以及如何使用 javascript 进行编程将非常困难。


编辑:

至于为什么会有变量和函数声明提升,那就是easily googlable.