Consider the following JavaScript code:
(function(){
foo();
function foo(){ alert('Hello, World!'); }
})();
In Firefox, Opera and Chrome, this behaves as expected; we get an alert. Now in contrast:
(function(){
if (true){
foo();
function foo(){ alert('Hello, World!'); }
}
})();
Firefox 3.6 and 4 (beta) (i.e. SpiderMonkey for both) throws an exception: foo is not defined
Chrome (i.e. V8) and Opera (i.e. whatever engine Opera uses) work as expected (by me).
Which is the correct behaviour, or is this left to implementations to decide?
FWIW, wrap it up in a function again and it's good to go in FF again:
(function(){
i开发者_高级运维f (true){
(function(){
foo();
function foo(){ alert('Hello, World!'); }
})();
}
})();
According to the ECMA-262 5th Edition spec, SourceElement
is defined to be:
SourceElement :
Statement
FunctionDeclaration
So, FunctionDeclaration
s and Statement
s are different. And blocks (e.g. if
) can only contain Statement
s:
Block :
{ StatementList opt }
StatementList :
Statement
StatementList Statement
So, no FunctionDeclarations
in if
s, grammatically, according to the spec. However, according to the comp.lang.javascript FAQ, Mozzila browsers and others implement a "function statement". This is allowed under section 16 of ECMA-262, Editions 3 and 5. Spidermonkey adds FunctionStatement. JScript adds FunctionDeclaration, however, JScript also has JScriptFunction. It appears the behaviour is left to implementations to decide.
Example of nonstandard FunctionStatement
:
try {
function Fze(b,a){return b.unselectable=a}
/*...*/
} catch(e) { _DumpException(e) }
Example of FunctionExpression
:
var Fze;
try {
Fze = function(b,a){return b.unselectable=a};
/*...*/
} catch(e) { _DumpException(e) }
Example of FunctionDeclaration
:
function aa(b,a){return b.unselectable=a}
This is due to different parsing symantec different browsers are using. Usually first declaration is evaluated. Since if condition encapsulate the declaration of foo method, it is not parsed. Ideally you should not create runtime conditional methods.
foo isn't parsed until the if statement is executed - And even within the if statement you're calling it before defining it. Although as you've said it works in Chrome etc. I would expect the behavior that FF exhibits if I was writing code like that.
I hope for the sake of maintainability you're not writing code like this - That's a confusing mess.
To be on a safe side write code this way:
var foo = function() { alert('Hello, World!'); } foo();
inside (function(){ })() block you'll get true private methods.
精彩评论