63

Possible Duplicates:
What is the difference between a function expression vs declaration in JavaScript?
Explain JavaScript's encapsulated anonymous function syntax

Why this:

(function () {
    //code
}());

and this:

var f = function () {
    //code
}();

works, while this:

function () {
    //code
}();

does not? It looks exactly the same - anonymous function defined, and immediately called. Can someone make a quotation from the JavaScript/ECMAScript standard which explains that?

UPDATE: Thanks for the answers everyone! So it's about function expression vs. function declaration. See this Stack Overflow answer, ECMAScript standard section 13, and this great article: Named function expressions demystified.

To recap answers:

  1. The first snippet is interpreted as an expression because the grouping operator, (), is applied - see ECMAScript standard section 11.1.6.

  2. In the second snippet, the function is interpreted as an expression because it's on the right-hand part of assignment operator, =.

  3. The third snippet doesn't have anything which allows the interpreter to read the function as an expression, so it's considered a declaration, which is invalid without an identifier (Gecko lets it pass however, but it chokes on following () grouping operator (as it thinks) applied to nothing).

Community
  • 1
  • 1
lxa
  • 3,234
  • 2
  • 30
  • 31

4 Answers4

22

The first two cases show function expressions, and can appear anywhere an expression like (1+1 or x*f(4)) would appear. Just like how 1+1, evaluates to 2, these expressions evaluate to a corresponding function.


The third case is a function declation statement, and can appear anywhere you can have other statements (like an if or while statement).

There is not much point in trying to declare an anonymous function via a Funcion declaration statements, since otherwise noone would get a reference to the function afterwards.


The reason you need the opening ( or the var x = like in the first two cases is that they force next bit to be parsed in an expression context. (just think how you cant do var x = if ..., for example). If you just put the function as the first thing it will be parsed as the declaration statement you don't want.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • _Funcion declaration statements cannot declare anonymous functions, since otherwise noone would get a reference to the function afterwards._ actually it can, try: `function () { }` (however it is indeed useless as it cannot be called neither in-place or otherwise) – lxa Jul 16 '11 at 18:30
  • UPDATE: `function () { }` (i.e. anonymous declaration) does work in Gecko but not in WebKit – lxa Jul 16 '11 at 18:40
  • @Ixa: edited the post to be less ambiguous anyway :) – hugomg Jul 16 '11 at 19:29
4

The first two are something called a function expression, meaning it's inline and interpreted as the JS code runs.

The 3rd is a function declaration and is interpreted when the code is compiled. Since it's interpreted at compilation, you can't immediately run it since none of the other code around it has been run yet.

To show an example:

// foo == undefined
// bar == function

function bar(){ .. }
var foo = function(){ ... }

// foo == function
// bar == function

Put simply, any time you have the word function without anything preceding it, it's a declaration. Any time something precedes it, it's an expression.

  • 2
    @PeterMortensen -- wtf? Don't make ___absolutely pointless edits___ to random posts. –  Apr 12 '15 at 12:15
1

Here's a simple way to think of it: If function is the first keyword on the line, the parser will interpret the rest of the line as a function declaration. In other words, it will think you're trying to write something like this, as if you've forgotten to name your function:

function foo(){ 
    // code
}

The way to get around this is either to wrap the entire function inside some parens or make it part of a variable assignment. In either case, you're putting function further back on the line and allowing the parser to recognize you're not writing a function declaration.

It kind of seems trivial to me to allow function to appear at the start of a line and still distinguish between function expressions and function declarations, but I guess it wasn't so trivial back when JavaScript was first being designed.

Andrew
  • 14,204
  • 15
  • 60
  • 104
  • Re: your last paragraph; there's simply no reason to complicate the language grammar for this edge case. Why would you ever need this? – Lightness Races in Orbit Jul 16 '11 at 18:00
  • @Tomalak Geret'kal Well, one (albeit questionable) reason: it would be consisent, i.e. if anything without identifier would be interpreted as expression (because declaration without identifier is useless anyway). – lxa Jul 16 '11 at 18:34
  • @Ixa: Indeed. More consistent perhaps, but of questionable benefit so why complicate the grammar? – Lightness Races in Orbit Jul 16 '11 at 18:36
  • @Tomalak Geret'kal, l personally think that the language designers never anticipated self-executing anonymous functions, so I don't find any fault here. But I do think they've made the grammar more complex by requiring you wrap self-executing anonymous functions inside parens. The fact that that you use `for` for iterating over arrays and objects (rather than creating a `foreach`, for example) is a sign of the flexibility they might have used here too. Why should it throw an exception when it's syntactically distinguishable from a declaration. It just bugs me. – Andrew Jul 17 '11 at 01:49
  • @Andrew: They're not "requiring" anything. You are not forced to use that horrid syntax. – Lightness Races in Orbit Jul 17 '11 at 01:51
  • @Tomalak Geret'kal, it sounds like you don't like the style. Though I don't see what that has to do with this question, I have no problem with that. But someone is requiring something here if doing it one way throws a syntax error. Besides, having read through the relevant bits of ECMA 262 now, I actually can't find anywhere that says you can't start a line with a function expression. So as @Ixa observes, this is actually a browser implementation issue and not a JS grammar issue. – Andrew Jul 17 '11 at 03:34
  • @Andrew: It's inherent from the grammar. If this syntax yields a function declaration, then it cannot also yield a function expression. – Lightness Races in Orbit Jul 17 '11 at 03:36
  • @Tomalak Geret'ka, then why does it work in FF? Read the ECMA spec. `function(){/*code*/}` is an expression. `function identifier(){}` is a declaration. Likewise, `for(exp1;exp2;exp3){/*code*/}` iterates over the elements of an array. `for(exp) {/*code*/}` iterates over the members of an object. There's no ambiguity here because the statements have different signatures. – Andrew Jul 17 '11 at 03:57
0

Anonymous functions are explained well in Stack Overflow question Why do you need to invoke an anonymous function on the same line?.

Community
  • 1
  • 1
Jason Gennaro
  • 34,535
  • 8
  • 65
  • 86