views:

1114

answers:

6

This code always work, and across browsers.

function fooCheck(){
  alert(internalFoo());

  return internalFoo();

  function internalFoo(){ return true; }
}
fooCheck();

I could not find a single reference to why it should work, though. I first saw this in John Resig's presentation note, but it just mentioned it. There's no explanation there or anywhere for that matter.

Could someone please enlighten me?

+1  A: 

I have only used javascript a little. I am not sure if this will help but it looks very similar to what you are talking about and may give some insight:

http://www.dustindiaz.com/javascript-function-declaration-ambiguity/

Eef
A: 

Some languages have the requirement that identifiers have to be defined before use. A reason for this is that the compiler uses a single pass on the sourcecode.

But if there are multiple passes (or some checks are postponed) you can perfectly live without that requirement. In this case, the code is probably first read (and interpreted) and then the links are set.

Gamecat
A: 

The body of the function "internalFoo" needs to go somewhere at parsing time, so when the code is read (a.k.a parsing) by the JS interpreter, the data structure for the function is created and the name is assigned.

Only later, then the code is run, JavaScript actually tries to find out if "internalFoo" exists and what it is and whether it can be called, etc.

Aaron Digulla
+4  A: 

The browser reads your html from beginning to end, and can execute it as it is read and parsed into executable chunks (variable declarations, function definitions, etc.) But at any point can only use what's been defined in the html before that point.

This is different from other programming contexts that process (compile) all your source code, link it together with any libraries you need, and construct an executable module, and which point execution begins.

You can define functions that refer to items (variables, other functions, etc.) that are defined further along, but you can't execute those functions until all the pieces are available.

As you become familiar with javascript, you will become intimately aware of your need to write things in the proper sequence.

Revision: To confirm the accepted answer (above), use Firebug to step though the script section of a web page. You'll see it skip from function to function, visiting only the first line, before it actually executes any code.

le dorfier
+26  A: 

The function statement is magic and causes its identifier to be bound before anything in its code-block* is executed. This differs from the function expression which is evaluated in normal top-down order, so if you changed the example to say:

internalFoo= function() { return true; };

it'd stop working. The function statement is syntactically quite separate from the function expression, even though they look almost identical and can be ambiguous in some cases.

This is documented in the ECMAScript standard, section 10.1.3. Unfortunately ECMA-262 is not a very readable document even by standards-standards!

*: the containing function or <script>-element.

bobince
I guess it's really not readable. I just read the section you pointed 10.1.3 and didn't get why the provisions there would cause this behavior. Thank's for the information.
Edu Felipe
A: 

For the same reason the following will always put foo in the global namespace:

if (test condition) {
    var foo;
}
Andrew Hedges
Actually, it's for very different reasons.The `if` block does not create a scope, while a `function()` block always creates one. The real reason was that the definition of global javascript names happens at compile phase, so that even if the code does not run, the name is defined. (Sorry it took so long to comment)
Edu Felipe