3

I thought that

function foo() { return 42; }

is mostly equivalent to

var foo = function() { return 42; }

except that foo.name differs in both cases. But regarding the scope, I thought it would be the same.

However, then I stumbled upon this code:

function demo() {
    return foo;

    function foo() { return 42; }
}

And demo() actually returns the foo function, i.e. demo()() == 42.

So, it seems that function evaluation is probably already done earlier, probably at compile stage.

Is my guess correct? Is that standard? (I'm using V8.)

(I just found this - it might be a duplicate.)

Community
  • 1
  • 1
Albert
  • 65,406
  • 61
  • 242
  • 386

3 Answers3

4

Functions defined like this:

function foo() { return 42; }

Are hoisted to the top of their containing function.

this looks to be a good article explaining scopes and hoisting.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
  • Here's another neat and friendly article: http://designpepper.com/blog/drips/variable-and-function-hoisting – matewka Mar 07 '14 at 14:02
1

To use your code example.

If you have this:

alert(foo());
function foo(){ return 42; }

It works, cause the code is interpreted as follows:

function foo(){ return 42; } // declaration is hoisted to the top
alert(foo());

DEMO - not using assignment


If you have this on the other hand:

alert(foo());
var foo = function() { return 42; }

The result is a runtime exception of undefined is not a function on line alert(foo()) as foo is not yet defined.

That is because the code is interpreted as follows:

var foo; // foo declaration is hoisted, but not the assignment
alert(foo()); // this will now fail as foo is undefined at this point
foo = function() { return 42; } // the assignment is not hoisted and stays where it is

DEMO - using assignment (open console to see error)


Additional Resources


MDN JavaScript Docs on Var - See hoisting section

Nope
  • 22,147
  • 7
  • 47
  • 72
0

The order of things when entering an execution context is that all function and variable declarations are processed before any code is run, therefore when a function declaration is used:

function foo(){}

the foo function will exist before any code is run. However, when a function expression is used with a variable declaration (aka an initialiser):

var foo = function(){};

while foo will be created before any code is run (because it is declared with var), it will initially be assigned the value undefined until the statement assigning the function is executed. Hence you can call a declared function before the declaration, but can only call a function defined by an initialiser after it has been initialised.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • The only way to declare *foo* without *var* is to use a function declaration, in which case it is still declared. Forget "hoisting", it is a jargon expression that should not be used, it is not in the language specification. And implicit creation of globals by assignment has nothing to do with so–called "hoisting" (see what happens when terms aren't defined?). Assignment to an undeclared variable creates a property of the global object with that name, similar to if it had be declared **except** that such properties are not created until the assignment code is executed and they can be deleted. – RobG Apr 26 '14 at 05:41
  • There is no hoisting, nothing moves, nothing is processed out of order. All code is first parsed, from the top to the very bottom. It is during this phase that declarations are processed. Then code execution beings. If the interpreter finds unparsable code at the very bottom, it will not execute any code at all. The error wasn't "hoisted" either. – RobG Apr 26 '14 at 14:02