1

Bootstrap css uses the following:

!function( $ ) {
}( window.jQuery )

That's different than the self-invoking anonymous function call that I originally learned:

(function($) {
})(jQuery);

Q: Is that just preference you think? I mean the not symbol instead of enclosing it in parenthesis.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
Phillip Senn
  • 46,771
  • 90
  • 257
  • 373
  • possible duplicate of [!function(){ }() vs (function(){ })()](http://stackoverflow.com/questions/8305915/function-vs-function) – Flambino Feb 28 '12 at 01:38

2 Answers2

3

"Q: Is that just preference you think?"

Yes, but using a unary ! operator, you can avoid a few bugs when you forget a semicolon before the IIFE, which can cause the () to be interpreted as a function call.

alert('foo')  // alerts 'foo'

(function() {  // TypeError: undefined is not a function
    alert('bar');
})()

Here the outer () is interpreted as a function call. It's trying to call whatever was returned from the alert() function, which of course returns undefined, which isn't a function.


alert('foo')  // alerts 'foo'

!function() {
    alert('bar');  // alerts 'bar'
}()

No troubles with this one, since the ! is a unary operator that only evaluates the operand to its right.

  • Wow. Thank you very much "am not i am". – Phillip Senn Feb 28 '12 at 01:58
  • @cf_PhillipSenn Also note, that Bootstrap ([on purpose!](http://www.wordsbyf.at/2011/10/31/i-dont-write-javascript/)) uses no semicolons, which makes the `!` syntax necessary. Or vice-versa: Using the `!` operator allows them to skip semicolons. – Flambino Feb 28 '12 at 02:19
  • The second example isn't a type error at all, unless you omit the opening (and corresponding closing) parentheseis. `(function(){}())` is identical to `(function(){})();`. The use of the `!` operator simply means the grouping parenthesis can be omitted, so it saves a single character. – RobG Feb 28 '12 at 02:31
  • @RobG: The second example? I didn't say that one was a type error. Only the first one. –  Feb 28 '12 at 02:38
  • The one that says `(function() { // TypeError...` is not a type error. Writing: `function(){...}()` is a syntax error though. – RobG Feb 28 '12 at 02:45
  • You are being misled, jsfiddle has bugs—in IE I get `TypeError: Object expected`. In a function expression using the grouping operator, the "call operator" can be inside or outside the group, it doesn't matter, as long as it's adjacent. – RobG Feb 28 '12 at 02:51
  • 1
    @RobG: I made no claim as to the proper position of the call operator on the anonymous function. What I said was that the *outer* set of `()` is being *interpreted* as a call operator, and is attempting to invoke the return value of the `alert()` call. The `alert()` returns `undefined`, which is why you get a `TypeError`. We can get rid of the *trailing* `()`, and get the same error. –  Feb 28 '12 at 02:54
  • ...[here's an example](http://jsfiddle.net/BGyaq/) to mess with. It replaces `alert()` with `test()`, which takes the string, alerts it, then returns a function that anticipates receiving a function, and invokes it. Because the outer `()` around the function is interpreted as a function call, the returned function is invoked, and the function in the `()` is passed, and invoked by the function we returned. I made the passed function also return a function so the final `()` could invoked it. Just add a `;` after `test()`, and the returned functions are no longer invoked. –  Feb 28 '12 at 03:14
  • Your post says that `(function(){alert('bar');})()` produces a type error. It doesn't, it's valid javascript and alerts "bar". The "outer ()" is a grouping operator that tells the parser that `function` is the start of a function expression. The trailing "()" is also a grouping operator, since it follows a function expression it's seen as containing a parameter list (albeit an empty one) and causes the function to be called. – RobG Feb 28 '12 at 03:26
  • @RobG: It produces a `TypeError` because it follows the `alert('foo')`, which doesn't terminate with a semicolon, so the code is interpreted as `alert('foo')(function(){...})()`. [Here's the example](http://jsbin.com/oxucaf/2/edit) in jsBin. Same result. I know you're probably going to claim that it has bugs. I also tested locally in Chrome and Firefox. Same result. –  Feb 28 '12 at 03:38
  • ...if you were right, then [the alternate example](http://jsfiddle.net/BGyaq/) I posted earlier would ignore the returned functions, and just alert `"foo"` and `"bar"`. This is obviously not the case. Insert the `;`, and you get the behavior you're expecting. –  Feb 28 '12 at 03:43
  • 1
    Cool, totally missed the bit about the semi-colon, must be old age catching up on me. If that's the purpose, I don't think it's a good idea. Better to fix the error than ignore it. – RobG Feb 28 '12 at 09:17
  • @RobG: Yes, if you normally use the grouping operator for the IIFE, then it would make sense to insert the semicolon as a fix. Using `!` as the regular replacement can be help avoid the bugs, but ultimately you're right; bugs should be found and fixed. I personally don't use semicolons for my NodeJS code, and I use `void` for my IIFE. –  Feb 28 '12 at 15:28
  • Are you saying use use `void function(){}()` ? – RobG Feb 29 '12 at 02:48
1

A statement starting with the function keyword is treated as a function declaration and must be followed by a name that is a valid identifier.

An anonymous function expression starts with the word function, but since there is no name, it can't be used where it might be confused with a function declaration. In most cases, the grouping operator is used to indicate a function expression:

(function() {
  /...
}());

or

(function() {
  /...
})();

You can also do:

var foo = function() {
}();

In all of the above, the function keyword isn't at the start of the statement so it's treated as the start of a function epxression. A name isn't required and the function can be immediately called.

It's the same with !function.... The parser sees the ! and says "what follows is an expression". When it gets to function it knows it's the start of a function expression.

Using !function… instead of (function…) saves a single character, and possibly creates a bit of confusion as it's a less common way to write a function expression.

RobG
  • 142,382
  • 31
  • 172
  • 209