在JavaScript中提升的顺序

mar*_*aft 10 javascript hoisting

function g () {
    var x;
    function y () {};
    var z;
}
Run Code Online (Sandbox Code Playgroud)

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

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

function g () {
    var x;
    function y () {};
    var z;
}
Run Code Online (Sandbox Code Playgroud)

理论2: var先到functions:

function g () {
    var x;
    var z;
    function y () {};
}
Run Code Online (Sandbox Code Playgroud)

理论3: function先到vars:

function g () {
    function y () {};
    var x;
    var z;
}
Run Code Online (Sandbox Code Playgroud)

哪种理论是正确的?

aps*_*ers 19

根据ECMAScript 5,第10.5节,首先提升函数,然后是变量声明,它指定了如何进行提升:

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

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

然后第8步处理var声明:

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

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

你也可以通过实验看到这个:

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

var g;
function g(){}
console.log(g);
Run Code Online (Sandbox Code Playgroud)

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

  • 要非常清楚,他说'函数'来自`var`s,这是OP中的理论3. (5认同)

tri*_*cot 7

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

  • var声明会被提升,但不会被提升(如果有的话)。一个var声明是没有效果;如果名称已经采取的function或其他var声明。
  • function 定义被提升——不仅声明名称,还声明它们的值,即函数。

所以下面两段代码:

(function () {
    console.log(typeof a);
    var a = 1;
    function a() { }
})();
Run Code Online (Sandbox Code Playgroud)

和:

(function () {
    console.log(typeof a);
    function a() { }
    var a = 1;
})();
Run Code Online (Sandbox Code Playgroud)

... 翻译成:

(function () {
    function a() { }
    var a;
    console.log(typeof a);
    a = 1;
})();
Run Code Online (Sandbox Code Playgroud)

和分别:

(function () {
    var a;
    function a() { }
    console.log(typeof a);
    a = 1;
})();
Run Code Online (Sandbox Code Playgroud)

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