質問

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...

役に立ちましたか?

解決

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.

他のヒント

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.

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;
}();
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top