66

I'm trying to read the Prototype source. I've come to this part.(Unfortunately, this snippet is in the beginnning).

What does this () mean?

  Browser: (function(){
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
    return {
      IE:             !!window.attachEvent && !isOpera,
      Opera:          isOpera,
      WebKit:         ua.indexOf('AppleWebKit/') > -1,
      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
    }
  })(),

I am referring to the last line before the comma?

Wayne
  • 59,728
  • 15
  • 131
  • 126
Teej
  • 12,764
  • 9
  • 72
  • 93
  • 1
    Note: according to jslint you should move the final executing parenthese inside the function parentheses: `(function() {...}())` – ErikE Jun 16 '11 at 05:46
  • @ErikE They ultimately do the same thing, though. See this question: http://stackoverflow.com/questions/6645766/why-are-parenthesis-used-to-wrap-a-javascript-function-call – Andrew Larsson Dec 05 '12 at 22:59
  • No argument that they do the same thing. It's a stylistic consideration, because by not putting the execution parentheses inside the outer pair, it can be unclear that what is being returned is the *result* of the function rather than *the function itself*. – ErikE Dec 05 '12 at 23:11

4 Answers4

48

The code is defining an anonymous function (the (function (){ ... }) bit) and then calling it (with no arguments). It then assigns the value to the Browser property of the object that is presumably being defined outside of your code snippet.

You could also define the function somewhere:

function myFunction() {
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
    return {
      IE:             !!window.attachEvent && !isOpera,
      Opera:          isOpera,
      WebKit:         ua.indexOf('AppleWebKit/') > -1,
      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
}

and then call it:

var foo = myFunction();

and then assign the value:

...
Browser: foo,
...

One downside with doing it that way is that you "pollute your namespace" with a function and a variable that you won't use anywhere else. The second issue is that you can't use the value of any locally-scoped variables in your function definition (the anonymous function behaves as a closure).

Frank Schmitt
  • 25,648
  • 10
  • 58
  • 70
41

(function () {}) creates an anonymous function.

Adding the () to the end calls the function that was just created.

In the case of this particular function, the anonymous function returns several properties to the Browser object. So, you end up with boolean values for, e.g., Browser.IE, Browser.Opera, etc.

Andrew Hedges
  • 21,688
  • 16
  • 67
  • 79
  • 3
    Which one is the proper notation? `(function(){}());` OR `(function(){})();` -- I"m talking about the parentheses order in the end. – ayjay Jun 19 '14 at 23:29
  • 3
    your first one is right @ayjay – Jonesopolis Jul 01 '14 at 15:17
  • 3
    @ayjay Actually either one is right, but Crockford uses the former, so I'd go with that. [http://javascript.crockford.com/code.html](http://javascript.crockford.com/code.html) – GFoley83 Jul 09 '14 at 05:05
  • @ajay I would say the best notation would be `!function(){}()` because it is slightly shorter. However, if you are using the closure compiler minifier (as you should be), then which ever you choose doesn't matter because the closure compiler will automatically convert your code to this shorter version. – Jack G Aug 06 '18 at 21:57
13

it calls the anonymous function that was just declared, effectively causing the "block" to be evaluated.

cobbal
  • 69,903
  • 20
  • 143
  • 156
5

It's a simple function call, no different than foo() except it's invoking an anonymous function literal, the result of the function is assigned to the Browser property.

meder omuraliev
  • 183,342
  • 71
  • 393
  • 434