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?
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:
- Evaluate Statement.
- 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.