为什么局部变量名优先于JavaScripts中的函数名?

时间:2012-10-31 10:51:19

标签: javascript

在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优化。但有没有技术解释来解释这种行为?

2 个答案:

答案 0 :(得分: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);
}());

有关完整的技术细节,建议您阅读section 10.5 of the spec

答案 1 :(得分:1)

声明JokerController函数的方式会导致函数定义被提升到范围的顶部。换句话说,实际运行的代码如下所示:

 function JokerController (){}
 var JokerController = 1;

如果将函数声明为匿名函数对象,引用/赋值给变量,则函数定义是表达式的一部分,因此不能在当前作用域的顶部悬挂。

See paragraph titled Function on MDN