This isn't just coming from The Good Parts.
Mozilla uses it in their docs, too:
Microsoft use it as well...
...as does Flanagan in the "Definitive Guide":
<snip>
Poor terminology choices are normal for both Flanagan and Microsoft,
and Mozilla documentation is still a little short of being good
(though certainly much improved over recent years). However, much
writing on the subject of javascript is (where it is not actually
inaccurate) aimed at audiences who have a great deal to learn before
they appreciate the subtleties; where moving in the direction of
understanding might be seen more productive than laying out the gory
details in full.
Most current implementations allow nesting:
if (blah) {
function blimm () {
....
}
}
Mozilla treats this as a function expression,
Not it does not.
not a function declaration, meaning that it will not be
evaluated unless blah is true.
With a function expression with optional Identifier (which is what the
above would be if it were a function expression) the resulting
function object can only be referenced using that Identifier from
inside the body of the function (all else being equal), because an new
object is added to the new function object's [[Scope]] and the
Identifier used to create a named property of that object to refer to
the function. Thus - blimm - is out of scope in the surrounding code,
if the code were a function expression.
In Mozilla browsers the function does become available using the
Identifier - blimm - in the containing scope, thus this is not a
function expression. In fact it is a function statement; a syntax
extension that is capable of allowing the conditional creation of a
function because being a Statement it can be evaluative inside a
block.
Mozilla also has FunctionDeclarations (which create function objects
during variable instantiation) and FunctionExpressions (which create
function object when evaluated, and do follow the ECMAScript rules
regarding optional Identifiers). The Mozilla docs might blur the
distinction but it exists regardless.
IE browsers also process the above code successfully (or at lest
without erroring) , but they see the function as a FunctionDeclaration
regardless of its 'illegal' context. Thus IE would create a function
object during variable instantiation, and so any surrounding
conditions (the - if(blah){ ... } - in this case) become redundant,
and the last FunctionDeclaration with any given name becomes the only
one available in the scope.
Most browsers (more or less) imitate one of these 'extensions' for
reasons of compatibility. But notations of which they should be
compatible with (JScript or JavaScript(tm)) seem to change. As I
recall (and my memory may not be accurate on this point) Opera had
switched from following JScript to following JavaScript, which Safari
has switched from following JavaScript to following JScript.
Obviously with two distinct interpretations of this code structure,
and minor browsers not necessarily sticking to following one or the
other (plus some related bugs that introduce some more variation)
using this type of code structure is seriously ill-advised. With
results that that may appear to 'work', but maybe only by coincidence
and for the time being. Plus (and most importantly) conditional
creation of function objects is (and always has been) possible using
pure ECMAScript constructs (by assigning the results of evaluating
function expressions to variables declared in the containing scope).
Interestingly the draft ES 3.1 spec is trying to switch
FunctionDeclaration to being a Statement. How that will work out
remains to be seen as the last draft I looked at (the one before the
current draft, which I haven't looked at yet) did not include any
processing or evaluation rules for their function statements (a bit of
an oversight as it makes the draft language non-viable as it stood).
Only source elements will be treated as function declarations.
<snip>
Only function declarations will be treated as function declarations
(in ES 3), Statements are SourceElements.
Richard.