Because it (foo
) is not defined ;-)
In this context, function
is a function-expression ("FunctionExpression") and not a function-statement ("FunctionDeclaration") -- there are two different productions in the grammar. Only the function-statement form [magically] assigns (and hoists the assignment) of the function name to the appropriate variable. Even functions created with a function-expression can have a name, it just happens to be optional, but there is no implicit assignment as with the other form.
[Edit: Apparently this is more quirky then I imagined. In any case, the above cases hold for a properly conforming browser. For instance Gecko has the "function statement extension, which is non-conforming, and IE/JScript exhibits different behavior, which is also non-conforming. Both of these are incorrect implementations according to the grammar specification.]
Consider the following, which should hopefully show why a ([more] conforming implementation) will sanely throw an exception:
// `function` is just an expression here -- there is no good reason for it to
// cause an implicit side-effect. And, according to the specification, it will not.
(function foo () {}).name // "foo", at least in FF
foo // undefined
On a side note: Any function production which is not a top-level statement or a statement directly inside a function block is a function-expression. The behavior of the following is quirky across browsers:
foo() // works in IE (this should never work)
if (true) {
// this is an INVALID GRAMMAR production, although it is accepted in browsers,
// with different operational semantics
function foo () {
}
}
foo() // works in FF and IE (this should never work)
Happy coding.
A little trip to the ECMAScript specification to talk about the grammar. The "rules" can be equally found there, although I find Ed. 5 to be written in the most confusing manner possible. (It misses for forest for all the trees...)
Grammar for FunctionExpression:
// There is a silly long expression tree to get here.
// Look it up if you want :)
FunctionExpression : function Identifier [optional] ( FormalParameterListopt ) { FunctionBody }
Grammar for FunctionDeclaration (what I refer to as a function-statement above), and associated "chain":
FunctionBody : SourceElements [optional]
Program : SourceElements [optional]
SourceElements : SourceElement
SourceElements SourceElement
SourceElement : Statement
FunctionDeclaration
FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody }
Note that there is no grammar rule for the "INVALID GRAMMAR" noted. The only way to get to a FunctionDeclaration is through a SourceElement which is only valid inside a FunctionBody or Program (which does not include other blocks like if
). "Normal expressions", as a FunctionExpression are restricted, as per below:
An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.
...and an apt note from the spec:
Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable difference, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations.