我试图理解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
答案 0 :(得分:5)
正如Benjamin Gruenbaum所说,const
和let
根本没有提升。
事实上,有适用于const
和var
的新规则,例如......
时间死区
现在,如果这些是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}}的顺序,您的代码就会崩溃。