在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优化。但有没有技术解释来解释这种行为?
答案 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;
如果将函数声明为匿名函数对象,引用/赋值给变量,则函数定义是表达式的一部分,因此不能在当前作用域的顶部悬挂。