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

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

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

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

理论 2: var s 在functions 之前:

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

理论 3: function s 在vars 之前:

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

哪个理论是正确的?

4

2 回答 2

24

首先提升函数,然后是变量声明,根据ECMAScript 5 第 10.5 节,它指定了提升的发生方式:

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

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

然后第 8 步处理var声明:

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

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

您还可以通过实验看到这一点

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

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

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

于 2015-01-31T00:06:41.540 回答
7

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

  • 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声明无效。在这两种情况下,结果是相同的。

于 2019-05-03T18:02:47.863 回答