【问题标题】:Order of hoisting in JavaScriptJavaScript 中的提升顺序
【发布时间】:2015-03-30 13:26:52
【问题描述】:
function g () {
    var x;
    function y () {};
    var z;
}

我想知道上面代码在被提升时的确切顺序。

理论 1:vars 和 functions 之间的顺序保持原样:

function g () {
    var x;
    function y () {};
    var z;
}

理论 2: vars 在 functions 之前:

function g () {
    var x;
    var z;
    function y () {};
}

理论 3: functions 在 vars 之前:

function g () {
    function y () {};
    var x;
    var z;
}

哪个理论是正确的?

【问题讨论】:

    标签: javascript hoisting


    【解决方案1】:

    函数首先被提升,然后是变量声明,每个 ECMAScript 5, section 10.5 指定如何提升:

    我们首先有第 5 步处理函数声明:

    对于代码中的每个 FunctionDeclaration f,按源文本顺序执行...

    然后第 8 步处理 var 声明:

    对于代码中的每个 VariableDeclaration 和 VariableDeclarationNoIn d,按源文本顺序执行...

    因此,函数的优先级高于var 语句,因为后面的var 语句不能覆盖先前处理的函数声明。 (子步骤 8c 强制执行条件“如果 varAlreadyDeclared 为假,则 [继续...]”,因此不会覆盖现有的变量绑定。)

    你也可以see this experimentally:

    function f(){}
    var f;
    console.log(f);
    
    var g;
    function g(){}
    console.log(g);

    两个log 调用都显示函数,而不是undefined 值。

    【讨论】:

    • 明确地说,他是说functions 在vars 之前,这是OP 中的理论3。
    • FWIW,这在最新版本中已经改变了一段时间。我相信两者的绑定现在是同时创建的(例如步骤 27),最后分配了实际的函数值(步骤 36)。但我可能误读了这一点。 ecma-international.org/ecma-262/9.0/…
    • 这对我来说很有趣,为什么 Ecma Scpesfication 接受这样的规则?赋予函数比 var 语句更高优先级的原因是什么?
    【解决方案2】:

    虽然 order 已由规范固定,但正如公认的答案所指出的那样,该顺序确实并不那么重要。

    • var 声明被提升,但不是它们的初始化(如果有的话)。如果名称已被 function 或其他 var 声明占用,则 var 声明无效。
    • function 定义被提升——不仅声明名称,还声明它们的值,即函数。

    所以下面两段代码:

    (function () {
        console.log(typeof a);
        var a = 1;
        function a() { }
    })();

    和:

    (function () {
        console.log(typeof a);
        function a() { }
        var a = 1;
    })();

    ...翻译成:

    (function () {
        function a() { }
        var a;
        console.log(typeof a);
        a = 1;
    })();

    分别:

    (function () {
        var a;
        function a() { }
        console.log(typeof a);
        a = 1;
    })();

    后两者其实是一回事。如果引擎首先处理提升的var 声明,则a 首先是undefined,但随后立即被覆盖为函数。另一方面,如果首先处理function 定义,则var 声明无效。在这两种情况下,结果都是一样的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-17
      • 1970-01-01
      • 2020-09-10
      • 2020-12-08
      • 2011-08-27
      相关资源
      最近更新 更多