views:

501

answers:

3

Have you ever taken a look under the hood at the JQuery 1.4 source code and noticed how it's encapsulated in the following way:

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

I've read an article on JavaScript Namespacing and another one called "An Important Pair of Parens," so I know some about what's going on here.

But I've never seen this particular syntax before. What is that undefined doing there? And why does window need to be passed and then appear at the end again?

+1  A: 

window is passed in like that just in case someone decides to redefine the window object in IE, I assume the same for undefined, in case it's re-assigned in some way later.

The top window in that script is just naming the argument "window", an argument that's more local that the global window reference and it what the code inside this closure will use. The window at the end is actually specifying what to pass for the first argument, in this case the current meaning of window...the hope is you haven't screwed up window before that happens.

This may be easier to think of by showing the most typical case used in jQuery, plugin .noConflict() handling, so for the majority of code you can still use $, even if it means something other than jQuery outside this scope:

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
Nick Craver
Thanks. This makes a lot of sense. Though, I think the answer is a combination of this and what @C.Zakas says.
DKinzer
@DKinzer I'm afraid I'm not C. Zakas ;)
Vincent
@Vincent, sorry about that :-)
DKinzer
+12  A: 

The undefined is a normal variable and can be changed simply with undefined = "new value";. So jQuery creates a local "undefined" variable that is REALLY undefined.

The window variable is made local for performance reasons. Because when javascipt looks up a variable, it first goes through the local variables until it finds the variable name. When it's not found, javascript goes through the next scope etc. until it filters through the global variables. So if the window variable is made local, javascript can look it up quicker. Further infomation: Speed Up Your JavaScript - Nicholas C. Zakas

Vincent
Thanks! that was a very informative video. I think you need to edit your response to say "the window variable is made local". I do think this is the best answer. I counted and found that the window object is called at least 17 times in the JQuery source code. So there's got to be a significant effect in moving the window into the Local Scope.
DKinzer
@DKinzer Oh yes, you're rght, of course it's made local. Glad I could help you =)
Vincent
+1  A: 

Others have explained undefined. undefined is like a global variable that can be redefined to any value. This technique is to prevent all undefined checks from breaking if someone wrote say, undefined = 10 somewhere. An argument that is never passed is guaranteed to be real undefined irrespective of the value of the variable undefined.

The reason to pass window can be illustrated with the following example.

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

What does the console log? The value of window object right? Wrong! 10? Wrong! It logs undefined. Javascript interpreter (or JIT compiler) rewrites it this way -

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

However, if you get the window variable as an argument, there is no var and hence no surprises.

I don't know if jQuery is doing it, but if you are redefining window local variable anywhere in your function for whatever reason, it is a good idea to borrow it from global scope.

Chetan Sastry