4

Possible Duplicate:
What advantages does using (function(window, document, undefined) { … })(window, document) confer?

I'm increasingly seeing code like this in libraries I've been using:

(function (window) {
    var Foo = function () {
    }

    window.Foo = Foo;
})(window);

The argument I've seen for doing this is to avoid working in the global scope when creating (pseudo) classes. But, correct me if I'm wrong, I always understood that window IS the global scope. I believe, when you create a global variable, you are really only adding a property to window anyway... Unless this is changing for ES5 strict?

So, basically, what's the point? The only benefit I can see to code organised like this is if you wanted to easily change the namespace of your classes at a later date by passing in an argument other than window.

Community
  • 1
  • 1
baseten
  • 1,362
  • 1
  • 13
  • 34
  • 1
    check this thread: http://stackoverflow.com/questions/5020479/what-advantages-does-using-functionwindow-document-undefined-windo and this one as well: http://stackoverflow.com/questions/2716069/how-does-this-javascript-jquery-syntax-work-function-window-undefined ... looks like it's mostly for performance reasons having to do with function lookup speed – user428517 Oct 22 '12 at 14:34
  • The answer is that while defining various variables inside the scope of this function, only the Foo member is attached to the window at the end. so you can have your logic vars do their business and remain outsite of the global scope's reach. – Omri Oct 22 '12 at 14:35
  • 1
    Other possibly useful threads: http://stackoverflow.com/questions/8275658/passing-window-and-undefined-to-an-immediately-invoked-anonymous-function-why http://stackoverflow.com/questions/4598479/what-is-the-purpose-of-the-anonymous-function-wrapper-in-jquery TL;DR: window can now be overridden, also marginal performance and minification benefits – jonvuri Oct 22 '12 at 14:36

3 Answers3

3

Infact, strict mode throws an exception if you forget to use var for any variable declaration. But that works even without using an outer closure.

Using this pattern is much more for protecting yourself from the outside javascript world. For instance, some other script overwrites window.undefined or any other variable, you can grab the value within that closure to savely access it from within.

For instance

(function _myApp( win, doc, undef ) {
    // app code
}( this, this.document ));

Also, when declaring variables with var, or creating function declarations, those are always stored within the current Activation Object respectively the Lexical Environment Record. That means, without using a Function context, you can easily overwrite methods and variables from some other point, because all of those would get stored in the current Context (which would be the global one)

So:

(function _myApp( win, doc, undef ) {
    var myVar = 42;

    function myFunc() {
    }
}( this, this.document ));

(function _myModule( win, doc, undef ) {
    var myVar = 42;

    function myFunc() {
    }
}( this, this.document ));

This works because of closure and Context, but if you would use the same code, without the Function Context, we would obviously overwrite our myVar and myFunc. This could happen from everywhere, within the same file or in another loaded script.

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • Yes and I'll be happy to see that exception. But there seems to be no scoping benefit to declaring a global this way from just a var with no outer closure. Security benefit is interesting as is slight performance and minification improvements. – baseten Oct 22 '12 at 14:49
  • @blask: interestingly, I benchmarked the access specifically on the `window` object some time ago and as result, it what always faster to access the *cached* reference than directly accessing `window`. Worst performance you'll gain by just relying on the browsers scope-chain lookup, means, just calling `setTimeout` for instance. – jAndy Oct 22 '12 at 14:54
0

As evil as global variables are, you need to have atleast one or there's no way to access your script. The code you provided is one way to create that one global variable. I prefer this way:

window.Foo = (function () {
    var func = function () {
        //  ...
    };

    return {
        func: func
    };
})();
jbabey
  • 45,965
  • 12
  • 71
  • 94
  • Which is Douglas Crockford's method as from here: http://stackoverflow.com/questions/5020479/what-advantages-does-using-functionwindow-document-undefined-windo The way I tend to write js I will only create Global Variables for my classes anyway. So having the additional scoping function seems unnecessary. Minification and Performance benefits are interesting though – baseten Oct 22 '12 at 14:44
  • @blask the additional scoping is the only way to achieve public and private methods, it is not unnecessary. this particular pattern is called [revealing module IIFE](http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript) – jbabey Oct 22 '12 at 15:03
  • yes I do this with an additional closure too, sorry I was referring specifically to passing the window object through in the manner of the original post – baseten Oct 22 '12 at 15:23
0

Your're right, but the difference is that the code inside of the function acts like an automatic init function.

(function (window) {
    var Foo = function () {
    }

    var Bar = 69; // not in global scope

    window.Foo = Foo; // in global scope
})(window);

As opposed to

var Foo = function () { // in global scope
}

var Bar = 69; // in global scope

and

var Foo = function () { // in global scope
}

function init () {
    var Bar = 69; // not in global scope
}
init();
SpaceFace
  • 1,492
  • 3
  • 15
  • 29
  • There's still no need to pass in window as a parameter. You can accomplish the same effect with an IIFE that returns the object you want to assign. See jbabey's answer. – jonvuri Oct 22 '12 at 14:39
  • That's the benefit of using the self calling anonymous function, but doesn't relate to the scoping issues – baseten Oct 22 '12 at 14:42