Nested function declarations and function expressions are supported by
Netscape 4 with JavaScript 1.3 and IE 4 (approx: JScript 2), about the
oldest browsers that remain viable as scriptable Internet user agents
(certainly the oldest considered for active support in a commercial
context, and often not then).
As is not unusual for such documents, the 3rd edition of ECMAScript was
formalising behaviour already common to implementations.
And has been a standard feature of browser scripting engine
implementations considerably longer.
Will I do?
Unless I'm missing something major (quite possible as I don't
have this thread in full), you seem to be suggesting that
function a() {
function b() {
}
}
is illegal. Is that correct? Well, in a code example, section
13.2 - Creating Function Objects, they have written almost
precisely the above.
If nested functions were not explicitly supported there would not be
much point in ECMA 262 (3rd edition) going into quite so much detail
about how the scope chain and the internal [[Scope]] properties are
handled, as there would be no ECMAScript circumstances where it would
make any difference (which is probably why the second edition can get
away with defining only one form of scope chain for any execution
context).
If you want the associated grammar:
FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
FunctionBody :
SourceElements
SourceElements :
SourceElement
SourceElements SourceElement
SourceElement :
Statement
FunctionDeclaration
Yes, function bodies may explicitly contain function declarations, and
function expressions may appear anywhere that a MemberExpression can be
used:-
| 11.2 Left-Hand-Side Expressions
| Syntax
| MemberExpression :
| PrimaryExpression
| FunctionExpression
| MemberExpression [ Expression ]
| MemberExpression . Identifier
| new MemberExpression Arguments
That suggests to me that it is perfectly legal to nest functions
to any degree. I haven't checked to any great extent to see if
the text notes limitations or exceptions, but I doubt there are
any.
One thing I had noticed in the grammar is that you may not place
function declarations directly within a statement. As far as I
can see, function statements may only occur in:
- The program source at the "root" level.
- Other functions (expressions or statements).
- An eval() argument.
That would make something like:
if(...) {
function myFunction() {
}
}
illegal. However, a quick test shows that (at least some)
browsers support it.
More involved tests would show extremely inconsistent handling of that
code. The production rules forbid a function declaration form appearing
within a block statement so the only valid ECMAScript interpretation of
that is as a function expression with optional identifier, and just
asserted (never assigned to anything or called, so a pointless
expression).
In practice browsers may take it as a function declaration (unless
explicitly parenthesised, which makes it unambiguously an expression)
and act on it during variable instantiation (effectively removing it
form its block context), and Mozilla browsers treat it as an expression
but erroneously (by ECMA 262) leak the optional identifier into the
containing scope (producing an effect indistinguishable form a
conditional function declaration (if such existed in ECMAScript).
Why you'd do something like this, though, is another
question.
You wouldn't, but an inner function expression, conditionally evaluated
and assigned, is completely normal.
Richard.