代码之家  ›  专栏  ›  技术社区  ›  Lajos Arpad

为什么块作用域函数在作用域之外工作?[副本]

  •  3
  • Lajos Arpad  · 技术社区  · 7 年前

    ES6 & Beyond 我现在在 second chapter . 在标题为“块作用域函数”的部分中,给出了一个示例:

    {
        foo();                  // works!
    
        function foo() {
            console.log("works!");
        }
    }
    
    foo();                      // ReferenceError
    

    (修订) console.log 是我为测试性而添加的。)

    我希望这段代码能够运行 foo 在第一次调用时成功,即使函数在调用下面定义,并且在第二次调用时由于引用错误而崩溃,正如本书所声称的那样。但是,如果我在Chromium(版本71.0.3578.98(正式构建)snap(64位))中运行此命令,则 function 调用已成功执行,并且 "works!" 两次输出到控制台。如果我在FireFox中运行相同的脚本,那么第一个函数调用不会记录任何内容,第二个函数调用(超出范围)将输出 “工作!” . 因此,Chromium和FireFox的表现各不相同,也与书中的预期不同。我在babeljs.io中传输了这个,结果是:

    "use strict";
    
    {
        // works!
    
        var _foo = function _foo() {
            console.log("works!");
        };
    
        _foo();
    }
    
    foo(); // ReferenceError
    

    foo is 定义为 作用 范围(关键字) var 使用,而不是关键字 let const ),因此可以从范围外访问,但范围外的调用未更改为 _foo ,因此我们将有一个错误,但是如果我们将脚本更改为

    {
        foo();                  // works!
    
        function foo() {
            console.log("works!");
        }
    }
    
    window["foo"]();                        // ReferenceError
    

    transpiler不会更改的名称 _福 . 通过所有这些实验,我得出了这样的结论:如果我想要一个块作用域函数,我需要显式地定义它,如:

    {
        foo();                  // works!
    
        let foo = function() {
            console.log("works!");
        };
    }
    
    foo();                      // ReferenceError
    

    但即使是第一次要求 由于暂时死区问题导致崩溃。所以,我的问题是:为什么块的作用域是 作用 在范围之外工作?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Pointy    7 年前

    正如Kyle在书中提到的,块中函数声明的语义在过去在不同的实现中有所不同。(这可以解释为什么在编码风格的注释中通常不鼓励在块内声明函数。)

    浏览器通常希望尽可能多的旧代码工作,因此有一个相当重要的变化,如 吊块 function "use strict"; 标志将ES6语义“打开”。旧代码(可能)不会有 “严格使用”; 无论在哪里,它都将继续以旧的方式行事(当然,这一直是有风险的)。