在JavaScript中提升的顺序

时间:2015-01-30 23:58:27

标签: javascript hoisting

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

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

理论1: varfunction之间的顺序保持原样:

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

理论2: var来到function之前:

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

理论3: function来到var之前:

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

哪种理论是正确的?

2 个答案:

答案 0 :(得分:17)

首先提升函数,然后按ECMAScript 5, section 10.5提升变量声明,指定如何进行提升:

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

  

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

然后第8步处理var声明:

  

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

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

您还可以see this experimentally

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

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

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

答案 1 :(得分:1)

尽管顺序由规范确定,但正如公认的答案所指出的那样,顺序实际上并不那么重要。

  • var声明被悬挂,但不初始化(如果有的话)。如果var或其他function声明已经使用了该名称,则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声明无效。在这两种情况下,结果都是相同的。