Hoisting is only part of the story here.
First, to explain hoisting:
When you use var
in a JavaScript program, you declare a variable. Wherever that variable is declared in a JS scope, it is hoisted to the top of that scope. JavaScript has only Global or Function scope; in the case of a function
function hoistAway() {
console.log(a);
var a = 5;
}
is equivalent to
function hoistAway() {
var a;
console.log(a);
a = 5;
}
As you can see, the declaration is hoisted, but the initialization is not. Thus, this code would log undefined
on the console, rather than 5. However, it would be satisfied that a
exists.
When you don't use var
, the declaration is not explicit, so it doesn't get hoisted. Thus:
function hoistAway() {
console.log(a);
a = 5;
}
will result in an error message.
In your examples:
window.Foo = Foo;
Foo
was never declared, so you get an error.
window.Foo = Foo;
Foo = function() {
...
};
Again, Foo was not declared, so no hoisting. For the record:
window.Foo = Foo;
var Foo = function() {
...
};
will not throw an error. However, only the declaration is hoisted, so if you did something like
var bob = {};
bob.Foo = Foo;
var Foo = function() {
...
};
then bob.Foo
would be undefined
. The special case of window.Foo = Foo
is weird because Foo
and window.Foo
are the same in the Global scope.
Finally:
window.Foo = Foo;
function Foo(){
...
};
works, because function declarations (as opposed to function expressions) are also hoisted; both the name and the definition gets hoisted, so this would work as intended.