Reputation: 17617
In JavaScript you can define function in a bunch of different ways:
function BatmanController () {
}
var BatmanController = function () {
}
// If you want to be EVIL
eval("function BatmanController () {}");
// If you are fancy
(function () {
function BatmanController () {
}
}());
By accident I ran across a unexpected behaviour today. When declaring a local variable (in the fancy way) with the same name as function the local variable takes presence inside the local scope. For example:
(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?
}());
Anyone know why var JokerController
isn't overwritten by function JokerController
? I tested this in Chrome, Safari, Canary, Firefox. I would guess it's due to some "look ahead" JavaScript optimizing done in the V8 and JägerMonkey engines. But is there any technical explanation to explain this behaviour?
Upvotes: 1
Views: 365
Reputation: 76413
The way you declare the JokerController
function causes the function definition to be hoisted to the top of the scope. In other words, the code that is actually run looks like this:
function JokerController (){}
var JokerController = 1;
If you declare a function as an anonymous function object, referenced/assigned to a variable, then the function definition is part of an expression, and therefore cannot be hoisted top the top of the current scope.
See paragraph titled Function on MDN
Upvotes: 1
Reputation: 166021
Because function and variable declarations are hoisted to the top of the scope in which they occur, yet assignments happen in place. Your code is effectively interpreted as this:
(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);
}());
For the full technical details I suggest you read section 10.5 of the spec.
Upvotes: 4