In JavaScript, what is the advantage of !function(){}() over (function () {})()? [duplicate]
Asked Answered
N

6

87

Possible Duplicate:
What does the exclamation mark do before the function?

I've long used the following for self-executing, anonymous functions in JavaScript:

(function () { /* magic happens */ })()

Lately, I've started seeing more instances of the following pattern (e.g., in Bootstrap):

!function () { /* presumably the same magic happens */ }()

Anyone know what the advantage is of the second pattern? Or, is it just a stylistic preference?

Nesta answered 28/9, 2011 at 17:2 Comment(5)
See this post it explains the difference between the two: #3756106Herriott
This answer in particular #3756106Gresham
I'd say this answer: #3756106Micrometry
They are for this purpose (forcing the evaluation of a function in expression context, calling it immediately ignoring its return value) equivalent, but IMHO I feel that using the Grouping Operator (the parentheses) is more "semantically correct" (and maybe more common and readable also), because that's the purpose of this operator, evaluate expressions... Just my two cents... Cheers!Wailoo
I think it's sad that this got closed as a duplicate - this question and all its answers are much better than anything in the duplicate.Amperage
M
82

These two different techniques have a functional difference as well as a difference in appearance. The potential advantages of one technique over the other will be due to these differences.

Concision

Javascript is a language where concision can be very important, because Javascript is downloaded when the page loads. That means that the more concise the Javascript, the faster the download time. For this reason, there are Javascript minifiers and obfuscators that compress the Javascript files to optimize the download time. For example, the spaces in alert ( "Hi" ) ; would be optimized to alert("Hi");.

Keeping this in mind, compare these two patterns

  • Normal closure:   (function(){})() 16 characters
  • Negated closure: !function(){}() 15 characters

This is a micro-optimization at best, so I don't find this a particularly compelling argument unless you are doing a code golf contest.

Negating the returned value

Compare the result value of a and b.

var a = (function(){})()
var b = !function(){}()

Since the a function does not return anything, a will be undefined. Since the negation of undefined is true, b will evaluate to true. This is an advantage to people who either want to negate the returned value of the function or have an everything-must-return-a-non-null-or-undefined-value fetish. You can see an explanation for how this works on this other Stack Overflow question.

I hope that this helps you understand the rationale behind this function declaration that would typically be considered an anti-pattern.

Martelle answered 28/9, 2011 at 17:11 Comment(4)
If the intent is just to execute the function (which is how I use it), then returning undefined actually feels more correct to me.Nesta
I gave you an upvote, but I have some trouble with 'concision'...Darnell
Trying to make Javascript source code concise just seems like a recipe for confusion. It should be as clear as possible — the very existence of this question makes it quite apparent that there is a great need for clarity in JS code! It can be passed through one of the minifiers you reference as part of the build process.Marrs
@Marrs Right. As I said, this is probably a useless micro-optimization. That said, minifiers won't perform this because it changes the behavior of the function and could cause code to break.Martelle
A
53

I always fall back on Ben Alman's IIFE piece for questions like this. It's the definitive as far as I'm concerned.

Here's the meat of the article:

// Either of the following two patterns can be used to immediately invoke
// a function expression, utilizing the function's execution context to
// create "privacy."

(function(){ /* code */ }()); // Crockford recommends this one
(function(){ /* code */ })(); // But this one works just as well

// Because the point of the parens or coercing operators is to disambiguate
// between function expressions and function declarations, they can be
// omitted when the parser already expects an expression (but please see the
// "important note" below).

var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// If you don't care about the return value, or the possibility of making
// your code slightly harder to read, you can save a byte by just prefixing
// the function with a unary operator.

!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// Here's another variation, from @kuvos - I'm not sure of the performance
// implications, if any, of using the `new` keyword, but it works.
// http://twitter.com/kuvos/status/18209252090847232

new function(){ /* code */ }
new function(){ /* code */ }() // Only need parens if passing arguments
Amperage answered 28/9, 2011 at 17:19 Comment(6)
Ooh, nice. I hadn't seen that. Thanks!Nesta
Ugh, javascript is a mess.Merwyn
JS isn't a mess, it's actually quite powerful - it just has some less-than-pretty syntax at points. ;)Milner
Take a look at coffeescript.org which cleans up the syntax but leaves it powerful features.Voroshilovsk
With all the additional syntax to remember(yes,true,on..do...false..no,false,off), I would argue CoffeeScript is more complex the Javascript. Although CoffeeScript has fewer characters, it isn't simpler. gist.github.com/1248911Bombacaceous
It does save 1 byte but I think it might also be an aesthetic thing. I don't think the ! is pretty but I think it is less ugly than the nested ((){}()) structure...Pianette
M
14

It seems that the key thing is that you're basically keeping the parser from interpreting the function as a function declaration, and instead it's being interpreted as an anonymous function expression.

Using the parens to group the expression or using the ! to negate the return are both just techniques of changing the parsing. It's then immediately invoked by the following parens. Any and all of these forms are having the same net effect in that regard, assuming no explicit return value:

(function(){ /* ... */ })(); // Arguably most common form, => undefined
(function(){ /* ... */ }()); // Crockford-approved version, => undefined
!function(){ /* ... */ }();  // Negates the return, so => true
+function(){ /* ... */ }();  // Attempts numeric conversion of undefined, => NaN
~function(){ /* ... */ }();  // Bitwise NOT, => -1

If you're not capturing the returned value, there's no significant difference. One could argue that the ~ might be a faster op since it's just flipping bits, or maybe ! is a faster op since it's a true/false check and returning the negation.

At the end of the day though, the way most people are using this pattern is that they're trying to break off a new level of scope to keep things clean. Any and all work. The latter forms are popular because while they do introduce an additional (typically unnecessary) operation, saving every extra byte helps.

Ben Alman has a fantastic writeup on the topic: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

Milner answered 28/9, 2011 at 17:21 Comment(0)
I
4

The first "pattern" calls the anonymous function (and has the result of its return value) while the second calls the anonymous function and negates its result.

Is that what you're asking? They do not do the same thing.

Iberia answered 28/9, 2011 at 17:7 Comment(0)
C
4

It is almost only stylistic preference, except for the fact that ! provides a function return (i.e. returns true, which comes from !undefined).

Also, it's one fewer character.

Cramer answered 28/9, 2011 at 17:10 Comment(0)
S
1

Well in the first case you are using ( ) to wrap the object you want to execute with the next set of (), and in the next case you are using operator that takes one argument (negation operator !) and you are making it implicitly wrap its argument (funcion) with ( ) so you actually get !(function () { })(), execute the function, and negate the result it returns. This can also work with -, +, ~ in the same principle since all those operators take one argument.

!function () { /* presumably the same magic happens */ }()
-function () { /* presumably the same magic happens */ }()
+function () { /* presumably the same magic happens */ }()
~function () { /* presumably the same magic happens */ }()

Why would you want to do this? I guess it is a personal preference or if you have big .JS and want to save 1 char per anonymous function call... :D

Selfsufficient answered 28/9, 2011 at 17:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.