4

I've seen this syntax for creating an anonymous constructor function in JavaScript:

var Application = Application || {};
!function(window, Application) {
   Application.property = {/*...*/}
   Application.method = function(){/*...*/}
}(window, Application);

I want to understand what the following parts here:

  1. What is the advantage of using first line (i.e. var o = o || {};) vs just stating var o = (function(){})();?
  2. Why ! is used in front of function?
  3. Why would I pass window or Application as parameters when they are global object?
  4. Is this the most convenient way for anonymous constructor function and how is this better than:

4a)

 var Application = { 
    property: {},
    method: function(){}
 }

or 4b)

 var Application = (function() {
    var method = function(){/*...*/}
    return {method:method};
 }());
Vad
  • 3,658
  • 8
  • 46
  • 81
  • it is not better than your alternative code. I would say it is worse. – akonsu Nov 18 '13 at 20:43
  • That's funny, but why? – Vad Nov 18 '13 at 21:26
  • The 2 snippets are not equivalent. `!function(){}()` is used instead of `(function(){})()`, see [this question](http://stackoverflow.com/questions/3755606/what-does-the-exclamation-mark-do-before-the-function) for details. – Vatev Nov 18 '13 at 21:49
  • 1. The advantage is that if an Application instance already exists, you won't write over it with a new instance. – net.uk.sweet Nov 19 '13 at 15:11

3 Answers3

2

The first line is to ensure that Application always exists, and is generally used in cases where it's expected that Application already should exist, and the function just augments the existing object. If it doesn't exist, this makes sure that we don't get an error for accessing properties of undefined. Your examples are only equivalent in the case where Application does not yet exist. In all other cases, your code will obliterate the existing Application, which is almost certainly not the intent.

The comment from Vatev explains what the ! does. It's another syntax for making the function in question become a self executing anonymous function. (Incidentally, it also takes the return value of the function - which is currently undefined, and flips its truthyness, so it evaluates as true. Since the result isn't stored in any variable, though, that's clearly not the purpose.)

Finally, why pass window and Application into the function and use it there? This is a safety feature, in case other code changes window or Application later on. It guarantees that within the anonymous function, window and Application are exactly what you expect it to be. In the shorthand example you gave, this may appear to not matter - after all, why protect these variables if you're using them immediately and not storing them? In many cases, you return something from this function, and then window and Application would be stored in the closure, so you'd retain the variables. It makes it safe from people who later on decide to say Application = {...}.

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
  • "safety reason" is not much of a reason: if the value is overwritten, it's overwritten – period. The only value where you can protect yourself is `undefined` by specifying it as a parameter, but not passing anything in (only needed for older browsers which allowed overwritin `undefined`). Other than that, aliasing global objects is useful for minification. – Ingo Bürk Nov 19 '13 at 15:21
  • 1
    @IngoBürk If you pass `Application` in to the function and store it in a closure, and outside of the closure, say `Application = "hello"`, within the closure, `Application` will still point to the original object. – Scott Mermelstein Nov 19 '13 at 15:23
  • Yes, but external code can still overwrite it if, for example, `Application = "Foo"` is called before the IIFE is called. Granted, it *is* a reason, but it's not fool-proof. I guess I wasn't clear on that, sorry. – Ingo Bürk Nov 19 '13 at 15:27
0

I don't know all of the answers but I'll try to answer what I can.

  1. Using var Application = Application || {}; simply means that you are dealing with scope. If the "Application" variable has already be defined, it will just mean that it inherits and is now available in the current scope. If not, the "||" part (means OR) means that it will be created as an empty object. You are dealing with creating an object and then acting on it, not just having the result given back raw. That's why you shouldn't use "o = (function() {...});". "o" would then be the result of the function and not the object.

  2. The use of "!function" causes it to be treated as an expression, but this can be tricky because you may have to think in opposites. E.g. !null means you are checking that it isn't null, not that you are checking for it to be null.

  3. Passing in the window and Application objects deal with scoping, again. It is explicitly passing them into the function, then returning them at the end. Think of this as putting clothes in the washing machine. You put them in, stuff can happen, then you get them back out. It's a really crude idea and isn't the best example, but it's how I thought of it a while back. You put clothes in, call then rinse function, then soap function, then rinse again, then spin to drain water.

  4. Hopefully someone else can answer that, I'm not sure what the differences are.

captbrogers
  • 475
  • 5
  • 15
  • 3. is also done a lot because it aliases those objects, which will allow it to be shortened, thus saving a few more bits and bytes upon minification. – Ingo Bürk Nov 19 '13 at 15:19
0

Since two answers so far neglected these two details: A pattern used by libraries like jQuery is using the following two parameters:

(function (window, undefined) {
    window.myPlugin = ...;
})(window);

There are two things going on here:

  • undefined is specified as a parameter, but not passed in. This way, undefined is guaranteed to have th expected value within the inner scope. This is only necessary for older browsers which allowed overwriting undefined (though it has always been considered bad practice to do so – it's just what libraries like jQuery do to avoid other code interfering with their code).

  • Aliasing a global object like window within the scope allows the code to be minified more (also works for undefined). Obviously, the more references you have to the aliased object(s), the more you will save:

.

(function(w,u){w.myPlugin=...;w.somethingElse=...;if(whatever===u){return;}})(window);

compared to

(function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})();

You won't save much with window since typically you don't wanna clutter the global object up anyway. But aliasing undefined can save you quite some space.

Ingo Bürk
  • 19,263
  • 6
  • 66
  • 100