JavaScript 中的提升顺序

IT技术 javascript hoisting
2021-01-29 03:23:55
function g () {
    var x;
    function y () {};
    var z;
}

我想确切地知道上面的代码在提升时变成什么顺序。

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

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;
}

哪个理论是正确的?

2个回答

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

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

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

然后第 8 步处理var声明:

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

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

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

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

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

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

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

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

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