113

I was recently comparing the current version of json2.js with the version I had in my project and noticed a difference in how the function expression was created and self executed.

The code used to wrap an anonymous function in parenthesis and then execute it,

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

but now it wraps the auto-executed function in parenthesis.

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

There is a comment by CMS in the accepted answer of Explain JavaScript’s encapsulated anonymous function syntax that “both: (function(){})(); and (function(){}()); are valid.”

I was wondering what the difference is? Does the former take up memory by leaving around a global, anonymous function? Where should the parenthesis be located?

Community
  • 1
  • 1
Kevin Hakanson
  • 41,386
  • 23
  • 126
  • 155
  • 1
    See also [Difference between (function(){})(); and function(){}();](http://stackoverflow.com/q/423228/1048572) and [Is there a difference between (function() {…}()); and (function() {…})();?](http://stackoverflow.com/q/3783007/1048572) – Bergi Jun 25 '14 at 16:22
  • Related: [Immediate function invocation syntax](http://stackoverflow.com/q/939386/1048572) (in JSLint) – Bergi Jul 16 '14 at 18:30
  • 1
    Also read about the [purpose of this construct](http://stackoverflow.com/q/592396/1048572), or check a ([technical](http://stackoverflow.com/q/4212149/1048572)) [explanation](http://stackoverflow.com/q/8228281/1048572) (also [here](http://stackoverflow.com/a/441498/1048572)). For why the parenthesis are necessary, see [this question](http://stackoverflow.com/q/1634268/1048572). – Bergi Jul 16 '14 at 22:45

4 Answers4

67

They're virtually the same.

The first wraps parentheses around a function to make it a valid expression and invokes it. The result of the expression is undefined.

The second executes the function and the parentheses around the automatic invocation make it a valid expression. It also evaluates to undefined.

I don't think there's a "right" way of doing it, since the result of the expression is the same.

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
meder omuraliev
  • 183,342
  • 71
  • 393
  • 434
  • 8
    JSLint wants "(function(){}());". JSLint says, "Move the invocation into the parens that contain the function." – XP1 Jul 18 '11 at 11:05
  • 28
    Actually you are not limited to those two, you can use just about anything that makes the compiler realize the function is part of an expression and not a statement, such as `+function(){}()` or `!function(){}()`. – Tgr Jul 25 '11 at 22:49
  • 50
    @XP1: JSLint wants lots of things that are specific to Crockford's *style* rather than being substantive. This is one of them. – T.J. Crowder Jul 28 '11 at 08:43
  • @T.J.Crowder. What would you recommend? jQuery uses the first style and Crockford uses the second. – Teej Feb 16 '12 at 07:55
  • 4
    @ThorpeObazee: It genuinely doesn't matter, so do whatever you prefer. I'd recommend against some of the more outre ones (`-function(){}();`, `!function(){}();`, and basically any other operator just before `function` also work, but I'd stick to versions using parens). I see the first a *lot* more than I see the second, and it's my preference; it makes more sense to me as well, but that's subjective. FWIW: http://jsbin.com/ejaqow – T.J. Crowder Feb 16 '12 at 08:38
  • @T.J.Crowder I have a feeling the V8 parser considers parens a hint that the function will be immediately executed, which is another reason to use them over the weirder options. – Flash Nov 06 '12 at 05:32
  • @Andrew: I doubt it, since other options can mean the same thing. The V8 parsing/compilation is fairly sophisticated these days. Heck, it's even a two-phase hotspot-style dohickey these days... :-) – T.J. Crowder Nov 06 '12 at 10:09
  • Here is a detailed description why it's better to move the invocation inside: https://medium.com/airbnb-engineering/immediately-invoked-function-expressions-and-parentheses-eeea53b39e0b – norlin Sep 04 '17 at 12:27
  • Eager avaluation is possible: This set `x` instantly to the value instead of function; `let x = (function(){return 123})()` –  Jun 12 '19 at 19:37
13

In that case it doesn't matter. You are invoking an expression that resolves to a function in the first definition, and defining and immediately invoking a function in the second example. They're similar because the function expression in the first example is just the function definition.

There are other more obviously useful cases for invoking expressions that resolve to functions:

(foo || bar)()
Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
  • 3
    For clarification to other readers (mainly because I didn't understand it at first myself :) ), foo and/or bar must already equal some function. (e.g. `foo = function(){alert('hi');}`. If neither are a function, an error is thrown. – Alexander Bird Apr 12 '12 at 18:53
  • 3
    @AlexanderBird A further clarification - It will also throw an error if `foo` is "truthy" but not a function. – JLRishe Aug 21 '14 at 05:40
11

There isn't any difference beyond the syntax.

Regarding your concerns about the second method of doing it:

Consider:

(function namedfunc () { ... }())

namedfunc will still not be in the global scope even though you provided the name. The same goes for anonymous functions. The only way to get it in that scope would be to assign it to a variable inside the parens.

((namedfunc = function namedfunc () { ... })())

The outer parens are unnecessary:

(namedfunc = function namedfunc () { ... })()

But you didn't want that global declaration anyways, did you?

So it it boils down to:

(function namedfunc () { ... })()

And you can reduce it even further: the name is unnecessary since it will never be used (unless your function is recursive.. and even then you could use arguments.callee)

(function () { ... })()

That's the way I think about it (may be incorrect, I haven't read the ECMAScript specification yet). Hope it helps.

hmakholm left over Monica
  • 23,074
  • 3
  • 51
  • 73
Cristian Sanchez
  • 31,171
  • 11
  • 57
  • 63
  • Note that `arguments.callee` is deprecated since ES5 (and forbidden in strict mode). – alexia Dec 26 '18 at 15:36
  • "The outer parens are unnecessary:" - I think they prevent errors when files are concatenated, otherwise you'd need a ! or something. – Jimmyt1988 Aug 12 '19 at 09:37
-2

The difference just exist because Douglas Crockford doesn't like the first style for IIFEs! (seriuosly) As you can see in this video!!.

The only reason for the existence of the extra wrapping () {in both styles} is to help make that section of code Function Expression, because Function Declaration cannot be immediately called. Some scripts / minify-ers just use +, !, - & ~ instead of too parentheses. Like this:

+function() {  
    var foo = 'bar';  
}();

!function() {  
    var foo = 'bar';  
}();

-function() {  
    var foo = 'bar';  
}();

~function() {  
    var foo = 'bar';  
}();

And all these are exactly the same as your alternatives. Choosing among these cases is completely on your own & makes no difference. { The ones with () produce 1 Byte larger File ;-) }

behkod
  • 2,647
  • 2
  • 18
  • 33