我正在尝试理解 ES6 词法作用域(使用 Node 运行时)。 考虑以下因素:
'use strict';
let x = 10;
function f() {
console.log(x);
console.log(y); // This should crash
}
let y = 5;
f();
摘自 O'Reilly 的书《学习 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.
但是,当我运行该程序(通过 Node )时,它输出: 10 5
对 console.log(y) 的调用是否违反了词法作用域规则?如果没有,为什么不呢?
编辑:为了将来引用,教科书(学习 Javascript 第三版 O'Reilly)的作者最近在“已确认的勘误表”中将此示例列为错误。上http://www.oreilly.com/catalog/errata.csp?isbn=0636920035534
最佳答案
正如 Benjamin Gruenbaum 提到的,let
和 const
根本不提升。
事实上,有一些新的规则适用于 let
和 const
,例如......
暂时死区
现在,如果这些是 var
声明,那么一切都会很清楚。但通过 let
和 const
,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)
语句定义函数时,实际的函数调用和变量访问仅发生在代码末尾。因此,变量绑定(bind)仅在此时进行评估(再次感谢@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();
的顺序,您的代码将会崩溃。
关于javascript - ES6/Node 中的词法作用域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36658438/