【发布时间】:2018-12-24 13:31:22
【问题描述】:
我正在阅读 Kyle Simpson:ES6 & Beyond,我在 second chapter。在标题为“块范围函数”的部分中给出了一个示例:
{
foo(); // works!
function foo() {
console.log("works!");
}
}
foo(); // ReferenceError
(console.log 是我为了可测试性添加的。)
我希望这段代码在第一次调用时成功运行foo,即使该函数是在调用下方定义的,并且在第二次调用时由于 ReferenceError 而崩溃,正如本书所声称的那样。但是,如果我在 Chromium(版本 71.0.3578.98(官方构建)快照(64 位))中运行它,则 function 调用都会成功执行,并且 "works!" 会两次输出到控制台。如果我在 FireFox 中运行相同的脚本,那么第一个函数调用不会记录任何内容,而第二个函数调用在范围之外输出"works!"。因此,Chromium 和 FireFox 的行为彼此不同,也与书中的预期不同。我已经在 babeljs.io 中编译了它,结果是:
"use strict";
{
// works!
var _foo = function _foo() {
console.log("works!");
};
_foo();
}
foo(); // ReferenceError
奇怪的是,foo is 定义为function 作用域,(使用关键字var 代替关键字let 或const),所以它可以从作用域外到达,但在作用域外调用范围没有更改为_foo,因此我们会出错,但是如果我们将脚本更改为
{
foo(); // works!
function foo() {
console.log("works!");
}
}
window["foo"](); // ReferenceError
转译器不会将foo 的名称更改为_foo。通过所有这些实验,我得出的结论是,如果我打算拥有一个块范围的函数,我需要明确定义它,例如:
{
foo(); // works!
let foo = function() {
console.log("works!");
};
}
foo(); // ReferenceError
但是由于时间死区问题,即使是第一次调用 foo 也会崩溃。所以,我的问题是:为什么块范围的 function 在范围之外工作?
【问题讨论】:
-
您正在查看的章节解释了这种情况。在 ES6 之前,实现是多种多样的。在“严格”模式下,Firefox 和 Chrome 都表现出 ES6 行为,将函数的范围严格限制在声明块中。
-
@Pointy 您似乎是对的,我已经对其进行了测试,并且行为与本书相符。但是,这本书没有提到严格模式的必要性,因此造成了混乱。如果您将其转换为答案,我会接受。