1

Possible Duplicate:
Why can I use a function before it's defined in Javascript?

As would be expected, the following code throws an error because Foo is not defined:

window.Foo = Foo;

Also as expected, this throws the same error:

window.Foo = Foo;
Foo = function() {
    ...
};

Curiously, this works just fine:

window.Foo = Foo;
function Foo(){
    ...
};

How is this possible? Isn't JavaScript interpreted line-by-line?

Community
  • 1
  • 1
user225643
  • 3,601
  • 5
  • 27
  • 22
  • 3
    [Hoisting](https://developer.mozilla.org/en/JavaScript/Reference/Scope_Cheatsheet#Hoisting). Also see http://stackoverflow.com/questions/7506844/javascript-function-scoping-and-hoisting. – Jonathan Lonowski Jul 16 '12 at 17:39

2 Answers2

4

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.

Dancrumb
  • 26,597
  • 10
  • 74
  • 130
0

The script is parsed first, allowing your code to call functions that are defined later on.

Paul Fleming
  • 24,238
  • 8
  • 76
  • 113
  • Ah! I also found this right after asking: http://kangax.github.com/nfe/ "Even if declaration is positioned last in a source, it will be evaluated foremost any other expressions contained in a scope." – user225643 Jul 16 '12 at 17:50
  • 4
    Yes the script is parsed first. That doesn't explain why the two types of functions behave differently. The difference is in the evaluation of function declarations vs expressions. –  Jul 16 '12 at 17:50
  • The conclusion is is true. However, it fails to mention why this is possible and how function *statements* are treated .. (function *expressions* are different) –  Jul 16 '12 at 17:52