Function inside if statement?

# Garrett Smith (17 years ago)

if(a) { function b(){ } }

A block can contain statements. A statement can't start with the function keyword.

Mozilla's Core JavaScript guide explains that of |b| should be evaluated as a functionExpression, but this isn't right. Source: developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Functions#Conditionally_defining_a_function

What should the above code do?

Should it be:

if(a) { (function b(){ }); }

SHould it be a function declaration, just like a variable statement?

if(a) { var b; }

Spidermonkey treats |b| as a function declaration as a statement (example).

No imlementations I know throw a SyntaxError; instead, the behavior is implementation-specific.

Garrett

# Brendan Eich (17 years ago)

On Feb 5, 2008, at 3:45 PM, Garrett Smith wrote:

if(a) { function b(){ } }

A block can contain statements. A statement can't start with the function keyword.

Mozilla's Core JavaScript guide explains that of |b| should be evaluated as a functionExpression, but this isn't right. Source: developer.mozilla.org/en/docs Core_JavaScript_1.5_Reference:Functions#Conditionally_defining_a_funct ion

That doc is wrong. Wiki-elves, sigh.

SpiderMonkey has for about a decade implemented three kinds of
function forms: definitions, expressions, and statements. This is an
example of the last -- it's a function definition, syntactically,
except produced as a child of another statement, possibly even a
block -- a position which the ES3 grammar cannot produce a function
definition. Only if control flow reaches the function statement does
it bind its name.

This is an extension allowed by ES3 chapter 16.

No imlementations I know throw a SyntaxError; instead, the behavior is implementation-specific.

Sure -- you knew that already by reading ES3, right? The problem with
standardizing is diverting effort from other tasks, and then forging
agreement on what function statements should mean. In IE, and IIRC
Opera based solely on IE, they are function definitions -- they
unconditionally bind their names on entry to the parent execution
context. That seems like a mistake, but it's hard to tell given other
IE bugs to do with named function forms (you know the one I mean well).

# liorean (17 years ago)

Just wanted to point out the thread starting here: uri:https://mail.mozilla.org/pipermail/es4-discuss/2007-March/000483.html.

It discusses this issue. Brendan gave this answer, a few replies in:

Since this is an ES3 extension, allowed by chapter 16, we could codify the majority-share practice, except that it sucks. We have so far avoided specifying function statements, preferring to leave them to implementations to experiment with, on into the ES4 future.

I did a summary of what the engines did in various browsers at: uri:https://mail.mozilla.org/pipermail/es4-discuss/2007-March/000495.html

The discussion detours a bit after that.

Also, Microsoft included these tests as section 2.9 in their "JScript Deviations from ES3" document at: uri:http://wiki.ecmascript.org/lib/exe/fetch.php?id=resources%3Aresources&cache=cache&media=resources:jscriptdeviationsfromes3.pdf

Note that the reason Safari according to that document doesn't give any results is that the test uses plain function declarations in the statement bodies. If the statement bodies had been wrapped in a statement list (curlies) then Safari would have given a profile very similar to that of Firefox except for the break-within-labelled-statement case, IIRC. In other words, to do a full set of tests one need to try both the statement-list wrapped versions and the plain function declaration versions, because they may have differing results.

# Mike Wilson (17 years ago)

Sorry if this was already covered by your summary, but I can confirm that if (true) function f() {} yields a SyntaxError in Safari 2.0.4, while if (true) { function f() {} } works fine.

Best Mike

# P T Withington (17 years ago)

On 2008-02-05, at 18:53 EST, Brendan Eich wrote:

SpiderMonkey has for about a decade implemented three kinds of function forms: definitions, expressions, and statements. This is an example of the last -- it's a function definition, syntactically, except produced as a child of another statement, possibly even a block -- a position which the ES3 grammar cannot produce a function definition. Only if control flow reaches the function statement does it bind its name.

This is an extension allowed by ES3 chapter 16.

I would endorse standardizing this behavior.

FWIW, the Openlaszlo compiler/translator extends es3 in a similar
fashion to support conditional compilation. An if that tests a
compile-time constant will be optimized away by the compiler.