Is there any difference between the two JavaScript templates?

Looking at some JavaScript libraries and other people's code, I saw two common patterns, I don’t know if there is a difference or an advantage in using one of them. The templates look something like this:

one.

var app = (function () { // Private vars // Module var obj = { prop: "", method: function () {} }; return obj; })(); 

2.

 (function () { // Private vars // Module var obj = { prop: "", method: function () {} }; window.app = obj; })(); 

Are these patterns the same or does one of them have an advantage or a different use than the other?

Thanks in advance.

+7
source share
5 answers

The second assumes the existence of an object named window in the parent area and assigns a property to it.

The first returns it to the caller to complete the task and does not depend on the definition of window (which is probably only inside the web browser).

So, I would say that the first one is definitely better (more autonomous, less dependent on the environment).

+4
source

tl; dr: choose one method and be consistent .


In my opinion, the first method has a slight advantage for readability. In my head, when I read it, I see that the “ app module is defined” and that everything inside this closure belongs to this module. This is a natural decomposition for me and imposes the object-oriented nature of the module that needs to be defined.

Another reason I prefer the first method is because it is cleaner to clear the scope to which the module is defined. Each module that you define does not have to be part of a global scope. Using the second method, if the region is not entered by passing in the Jared Farrish parent object, its jQuery example illustrates, then you risk breaking your code if you decide to change the name of this parent object. This example illustrates the point:

 var namespace = { subns: { ... } }; (function() { var module = { ... }; namespace.subns.someModule = module; }()); 

At any time when the namespace or subns identifiers change, you also need to update this module and any other module that follows this template and add itself to the same object.

In general, neither method, nor method two (with dependency injection) are “better” than the others, it's just a matter of preference. The only advantage that may arise in this discussion is that you have to choose one method and be consistent .

+2
source

They both do the same thing to create an object in the global namespace during code execution.

One of them is no more "hard-coded" than the other, since none of them performs any prototype functions in which you could create clones of an object with a new keyword. In my opinion, this is a matter of preference.

For example, jquery does something similar to the last:

 (function( window, undefined ) { // Use the correct document accordingly with window argument (sandbox) var document = window.document; var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, ... 

But the prototype JS library does the first:

 var Prototype = { Version: '1.6.1', 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 don’t know a single reason why one is better than the other, or that they perform their task differently (to create an application object in the window namespace).

+1
source

In the first example, if the app is defined inside another function, the app will be available only in this local area, while in the second example, the app variable is explicitly assigned to the global area.

In the second example, the app will only be assigned to the global scope if it is defined in the global scope outside of functions.

0
source

The second form has a slight advantage in that you have a fully autonomous function; for example, you could have a standard header and footer for your JS files.

The part I am not selling completely is the local variable inside the block. I prefer this:

 (function () { // Private vars // Module window.app = { prop: "", method: function () {} }; })(); 

although this is slightly reduced when you do more than one, for example, create an object with several methods, and not with one object, as in this example.

-2
source

All Articles