ES6 / Node中的词法范围

时间:2016-04-15 23:35:56

标签: javascript node.js ecmascript-6 scoping lexical

我试图理解ES6词法范围(使用节点运行时)。 请考虑以下事项:

'use strict';
let x = 10;
function f() {
   console.log(x);
   console.log(y); // This should crash
}

let y = 5;
f();

从O' Reilly书中解释"学习Javascript":

  

词法作用域意味着您定义函数的范围内的任何变量(与您调用它时相反)都在函数的范围内。

但是,当我运行此程序(通过节点)时,它输出: 10 5

是不是对console.log(y)的调用违反了词法范围规则?如果没有,为什么不呢?

编辑:为了将来参考,似乎教科书的作者(Learning Javascript 3rd Edition O' Reilly)最近将此示例列为"已确认的勘误"中的错误。在http://www.oreilly.com/catalog/errata.csp?isbn=0636920035534

1 个答案:

答案 0 :(得分:5)

正如Benjamin Gruenbaum所说,constlet根本没有提升。

事实上,有适用于constvar的新规则,例如......

时间死区

现在,如果这些是let声明,一切都会很清楚。但是对于const'use strict'; var x = 10; console.log(x); console.log(y); // This should NOT crash var y = 5; ,ES6引入了temporal dead zone.的新概念。这包括一个新的,微妙的动态。

让我们看看两个例子:

典型的吊装可以在这样的例子中起作用:

var

但是如果我们用let声明替换'use strict'; let x = 10; console.log(x); console.log(y); // This crashes: ReferenceError: can't access lexical declaration `y' before initialization let y = 5; 声明,它就会崩溃:

var

为什么这会崩溃?

由于与let分配不同,在实际let语句之前访问使用console.log(y)定义的变量无效(它们位于暂时死区)。

<强> 2。在这种情况下,时间死区

然而,在这种情况下,时间死区不是问题。为什么呢?

因为虽然事先用'use strict'; let x = 10; function f() { console.log(x); console.log(y); // This should not yet crash } let y = 5; f(); // console.log(y) is only called here 语句定义了函数,但实际的函数调用和变量访问只发生在代码的末尾。因此,变量绑定仅在此时进行评估(再次感谢@BG):

let y = 5;

如果您要颠倒f();和{{1}}的顺序,您的代码就会崩溃。