1

在 JavaScript 中,您可以通过多种不同的方式定义函数:

function BatmanController () {
}

var BatmanController = function () {
}

// If you want to be EVIL
eval("function BatmanController () {}");

// If you are fancy
(function () {
    function BatmanController () {
    }
}());

今天偶然遇到了一个意想不到的行为。当声明一个与函数同名的局部变量(以花哨的方式)时,局部变量出现在局部范围内。例如:

(function () {
    "use strict";

    function BatmanController () {
    }

    console.log(typeof BatmanController); // outputs "function"

    var RobinController = function () {
    }

    console.log(typeof RobinController); // outputs "function"

    var JokerController = 1;
    function JokerController () {

    }
    console.log(typeof JokerController); // outputs "number", Ehm what?
}());

有谁知道为什么var JokerController不被覆盖function JokerController?我在 Chrome、Safari、Canary、Firefox 中对此进行了测试。我猜这是由于在 V8 和 JägerMonkey 引擎中完成的一些“前瞻性”JavaScript 优化。但是有什么技术解释可以解释这种行为吗?

4

2 回答 2

4

因为函数和变量声明被提升到它们发生的范围的顶部,但赋值发生在适当的位置。您的代码被有效解释为:

(function () {
    "use strict";

    function BatmanController () {} // Declarations are hoisted
    function JokerController () {}

    var RobinController, // Declarations are hoisted
        JokerController;

    RobinController = function () {} // Assign function to RobinController

    // outputs "function" (declaration was hoisted to top of scope)
    console.log(typeof BatmanController);

    // outputs "function" (assignment of number hasn't happened yet)
    console.log(typeof RobinController);

    JokerController = 1; // Assign number to JokerController

     // outputs "number" (assignment of number has now happened)
    console.log(typeof JokerController);
}());

有关完整的技术细节,我建议您阅读规范的第 10.5 节

于 2012-10-31T10:53:01.510 回答
1

声明JokerController函数的方式会导致函数定义被提升到作用域的顶部。换句话说,实际运行的代码是这样的:

 function JokerController (){}
 var JokerController = 1;

如果您将函数声明为匿名函数对象,引用/分配给变量,则函数定义是表达式的一部分,因此不能提升到当前范围的顶部。

请参阅 MDN 上标题为 Function 的段落

于 2012-10-31T11:02:23.867 回答