ES6 / Node 中的词法范围

Lexical scoping in ES6 / Node

我正在尝试理解 ES6 词法范围(使用节点 运行time)。 考虑以下因素:

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

let y = 5;
f();

从 O'Reilly 书中转述 "Learning Javascript":

Lexical scoping means whatever variables are in scope where you define a function from (as opposed to when you call it) are in scope in the function.

然而,当我运行这个程序(通过节点)时,它输出: 10 5

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

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

正如 Benjamin Gruenbaum 所提到的,letconst 根本没有提升。

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

时间死区

现在,如果这些是 var 声明,一切就都清楚了。但是随着 letconst,ES6 引入了 temporal dead zone. 的新概念,这包括一个新的、微妙的动态。

我们来看两个例子:

经典提升将在这样的示例中工作:

'use strict';
var x = 10;

console.log(x);
console.log(y); // This should NOT crash

var y = 5;

但是如果我们用 let 声明替换 var 声明,它会崩溃:

'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定义的变量是无效的(它们处于临时死区)。

2。这种情况下的时间死区

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

因为虽然我们事先用 console.log(y) 语句定义函数,但实际的函数调用和变量访问只发生在代码的末尾。所以变量绑定只在此时进行评估(再次感谢@BG):

'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

如果您颠倒 let y = 5;f(); 的顺序,您的代码将会崩溃。