2

I've seen these different patterns when calling a JavaScript function expression:

Pattern #1

var global = function () {
    return this;
}();

Pattern #2

var global = (function () {
   return this;
}());

Pattern #3

var global = (function () {
    return this;
})();

In my testings all seem to work (at least with most current browsers). To my "taste", pattern #3 is better, since it's more explicit than #1, and it returns the function before actually calling it, as opposed to #2.

But I was wandering if there is a preferred or more correct one...

  • 1
    I would not recommend #1, since it will not work if you're not assigning the return value to a variable (e.g. if you're only defining the function to establish a closure, and are calling it in a void context), and you'll have to remember when to use which construct. – lanzz Jun 03 '12 at 15:31
  • @amnotiam: Try to run `function() { console.log('foobar') }();` (without assigning its result to a var) and you'll get an error. You can use this style when you use the function call in an expression, but when you're just calling the function and disregarding return value, you'll need to use one of the other patterns. It is unproductive to have to think which pattern you need in two similar situations, when there are patterns that work in both. – lanzz Jun 03 '12 at 16:01
  • @lanzz: I didn't understand at first that you meant without the presence of the assignment operator, or some other operator to evaluate `function` as part of an expression. I thought you were only talking about the return value. –  Jun 03 '12 at 16:02

3 Answers3

2

So, the initial problem is that the code below:

function () {

}();

Raises an exception. That's because the JS parser is not able to automatically determined if it's a function declaration or a function expression. All the patterns you described are used to explicitly tell to JS "hey dude, that's an expression". But in you specific case you don't have that problem, because if you have a variable in front, JS is perfectly able to understand that is an expression, not a declaration,and it doesn't raise any syntax error.

In that specific case there is no need to any "hack", you can simply have:

var _global = function () {

}();

And that's it. The question now is: which "hack" use when you need to have a immediate function invocation without any variable? All the pattern you described are okay, Crockford tends to prefer this one:

(function(){

}());

That's makes sense to me, at least because you have a full isolated block, compared to:

(function(){

})();

However, if you join your code with other scripts, or you have previous code, you could end up with some problem if they don't use semicolon at the end:

a = b + c
(function() {

}());

In this scenario JS consider c a function's call:

a = b + c(function() { }());

To avoid that, developers usually add a semicolon in front, just to be safe:

;(function() {

}());

I personally prefer some operator instead, like the bang (!):

!function () {

}();

With that you don't have the issues you have using parenthesis. Less characters, and gives to me a sense of "execution". But, like the other approach, it's an hack and it's a matter of personal taste. For instance Crockford dislike A LOT that bang stuff.

ZER0
  • 24,846
  • 5
  • 51
  • 54
  • Thanks for the detailed answer! I didn't know about ; and !, but I didn't like them! They might work, but then it's even more cryptical! Maybe it's my "Zen of Python" kicking in: there should be (one) obvious way to do it! :-) – dalembertian Jun 07 '12 at 04:01
  • As I said, they are hacks and therefore it's a matter of personal taste. :) Also, if you're always in the first scenario, where you have to set a variabile, you don't need them. But, if you're in the others, you have to use or `;` or an operator (like `!`) there is no alternatives if you want to be sure you won't have any weird bugs; or if you want to create a library that can use independently by you or others. That's because some people doesn't use semicolon at the end of the line, relying to the ASI (Automatic Semicolon Insertion), but in some cases like this one, is necessary. – ZER0 Jun 07 '12 at 10:44
0

They all work fine, you can use any one of them, the recommended pattern by Crockford though is Pattern #2:

var global = (function () {
   return this;
}());

I personally find Pattern #3 easy to work with though since it is easy to follow:

var global = (function () {
    return this;
})();

BTW there are other patterns / shorthands too that use !, +, etc characters:

! function(){
  return this;
}();
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
0

I prefer pattern one as when defining functions as properties of objects your syntax and grow to be very verbose. Pattern #1 is simple to follow; you define a function and then call it. Pattern 3 does the same but with and extra set of () to follow. This verbosity has a cost of productivity in my opinion.

As you have said they are all correct but I find it important to remember "Occam's razor" => when all things are equal simpler explanation (expression) is better than a more complex one.

secretformula
  • 6,414
  • 3
  • 33
  • 56