ES6标准提出了Temporal Dead Zones,在评估词法绑定之前,无法以任何方式进行变量引用。那么词汇环境初始化时的变量创建意味着什么呢?
使用var
声明声明变量可能对程序员以前有意义,但是现在有了TDZ,为此目的,javascript开始表现得像java吗?除了javascript解释器的工作方式之外,还有什么理由我们首先提升(因此是TDZ)吗?
如果代码后面因为执行顺序遇到词法绑定,即使代码在词法之前出现,会发生什么?
let abc = f();
let b;
f(){ return b;}
像java这样的传统编程语言何时创建变量?遇到变量声明时?或者当词汇范围初始化时?
答案 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.