Why can't I use a Javascript function before its definition inside a try block?

Chris Noe picture Chris Noe · Nov 1, 2010 · Viewed 8.9k times · Source

As discussed here, function definitions can be used before they're defined. But as soon as a section of code is wrapped in a try block, this ceases to be the case.

This displays "Hello world":

hello();
function hello() { alert("Hello world"); }

But this displays "ReferenceError: hello is not defined":

try {
  hello();
  function hello() { alert("Hello world"); }
} catch (err) {
  alert(err);
}

So there is clearly something "special" about a try block with respect to function declarations. Is there any way to get around this behavior?

Answer

BGerrissen picture BGerrissen · Nov 1, 2010

Firefox interprets function statements differently and apparently they broke declaration hoisting for the function declaration. ( A good read about named functions / declaration vs expression )

Why does Firefox interpret statements differently is because of the following code:

if ( true ) {
    function test(){alert("YAY");}
} else {
    function test(){alert("FAIL");}
}
test(); // should alert FAIL

Due to declaration hoisting, function test should always alert "fail", but not in Firefox. The above code actually alerts "YAY" in Firefox and I suspect the code that makes that happen finally broke declaration hoisting altogether.

I assume Firefox turns function declarations into var declarations when they are located in if/else or try/catch statements. Like so:

// firefox interpretted code
var test; // hoisted
if (true) {
   test = function(){alert("yay")}
} else {
   test = function(){alert("fail")}
}

After a brief debate with Šime Vidas, I have to say that Firefox's dealing with function declarations is non-standard, because of:

The production SourceElement : Statement is processed for function declarations by taking no action.
The production SourceElement : Statement is evaluated as follows:

  1. Evaluate Statement.
  2. Return Result(1).

Both FunctionDeclaration and Statement are SourceElements, ergo, there should be no FunctionDeclarations inside a statement (if/else, try/catch). Give Šime Vidas a brownie!

Try/catch is basically another form of if/else and probably uses the same exception code.