What advantages does using (function(window, document, undefined) { ... })(window, document) confer?
Why are window and document being fed in instead of just being accessed normally?
Generally to fasten the identifier resolution process, having them as local variables can help (although IMO the performance improvements may be negligible).
Passing the global object is also a widely used technique on non-browser environments, where you don't have a window
identifier at the global scope, e.g.:
(function (global) {
//..
})(this); // this on the global execution context is
// the global object itself
Why the heck is undefined being passed in?
This is made because the undefined
global property in ECMAScript 3, is mutable, meaning that someone could change its value affecting your code, for example:
undefined = true; // mutable
(function (undefined) {
alert(typeof undefined); // "undefined", the local identifier
})(); // <-- no value passed, undefined by default
If you look carefully undefined
is actually not being passed (there's no argument on the function call), that's one of the reliable ways to get the undefined
value, without using the property window.undefined
.
The name undefined
in JavaScript doesn't mean anything special, is not a keyword like true
, false
, etc..., it's just an identifier.
Just for the record, in ECMAScript 5, this property was made non-writable...
Is attaching the object we're creating directly to window a particularly good idea?
It's a common way used to declare global properties when you are on another function scope.
Using 'window', 'document' and 'undefined' as arguments in anonymous function that wraps a jQuery plugin
When you write a function like:
(function (foo, bar) {
return foo.getElementById(bar);
})(document, "myElement")
then the function is immediately called with arguments document
and "myElement"
for parameters foo
and bar
. Therefore, inside the function, foo.getElementById(bar)
is equivalent to document.getElementById("myElement")
.
Similarly, in your plugin example, you are immediately calling the function with the arguments jQuery, document, window
.
What indeed is meant by
function($)
?
The $
simply represents a reference to a jQuery
object that is passed in to the wrapper function. Later, when the anonymous function is called with (jQuery, window, document)
, the $
reference inside the function references the jQuery
object. This is done for a number of reasons, not least of which is that $
is quicker to type. It also allows the user to apply your plugin in wrapper to a particular instance of jQuery
, produced perhaps by jQuery.noConflict()
.
Why should I include
window
,document
andundefined
as arguments offunction($)
?
You don't need to include these. The original author's reasoning is that assigning function-local variables to reference these will shorten the time it takes to resolve these variables. I assert that the savings are negligible; I personally wouldn't bother unless I used a lot of references to window
and/or document
.
As for undefined
, the original author's purpose in including this is to ensure that someone hasn't altered the undefined
global variable in EcmaScript 4 (edit: actually ECMAScript 3 -- version 4 never made it) or earlier. Again, I can't envision this problem cropping up. If you're truly worried that this could be a problem, just include something like this in your function:
if(typeof undefined !== "undefined") {
undefined = void 0;
}
If I do it, how do I access the actual
window
anddocument
objects?
All you have to do is make sure that the function call at the end of your anonymous function passes in the actual (jQuery, window, document) parameters. Or, don't include the window
and document
arguments in your function signature. Either way, you will be referring to the actual objects, regardless of the level of indirection.
undefined
what, and why?
undefined
is a global variable of type "undefined". Fields that have not been initialized are exactly equal (===) to undefined. It allows the programmer to differentiate between a deliberately null value and a simple uninitialized one. In ECMAScript 5 and later, undefined
is read only. Prior to that, it is possible that other code could modify the value of undefined
. You can always get the true value undefined
with the expression void 0
... as in myUndefinedVar = void 0;
.
Javascript function has (document) slapped on at the end?
It's a self executing function that is passing document
as an argument.
This could be rewritten as:
var myFunc = function(d) {
// code here
};
myFunc(document);
How does this JavaScript/jQuery syntax work: (function( window, undefined ) { })(window)?
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 JavaScript 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 information: Speed Up Your JavaScript - Nicholas C. Zakas
Declaration function inside ( )
In your example, I see no reason for the parentheses.
For immediately invoked functions, Douglas Crockford recommends and provides a code sample as below. Source is http://javascript.crockford.com/code.html
When a function is to be invoked immediately, the entire invocation
expression should be wrapped in parens so that it is clear that the
value being produced is the result of the function and not the
function itself.
var collection = (function () {
var keys = [], values = [];
return {
get: function (key) {
var at = keys.indexOf(key);
if (at >= 0) {
return values[at];
}
},
set: function (key, value) {
var at = keys.indexOf(key);
if (at < 0) {
at = keys.length;
}
keys[at] = key;
values[at] = value;
},
remove: function (key) {
var at = keys.indexOf(key);
if (at >= 0) {
keys.splice(at, 1);
values.splice(at, 1);
}
}
};
}());
JavaScript function with 'undefined' parameter
Creates a local undefined
in case someone redefines undefined
somewhere in the scope chain.
Also provides a faster lookup since undefined
is a global property, so the scope chain traversal is reduced.
Difference between (function(window){}) and (function(){})
The semantic difference is small in this case. However, if window
is used a lot throughout the code, aliasing it as a local variable allows for better minification.
(function (window) { window['foo'] = window['baz']; })(window);
can be minified to
(function(w){w['foo']=w['baz']})(window)
Without the local alias, window
could not be reduced and the minification would instead be
(function(){window['foo']=window['baz']})()
There are other reasons as well as other use-cases for similar tricks. Have a look at this question to find more in-depth explanations.
What is the purpose of a parameter named undefined in a JavaScript function?
What this is doing, is reassigning undefined
to undefined
inside that closure. Thats a failsafe. Because other code may accidentally do something like
undefined = something;
console.log(undefined); // will output 'something'
And thats valid in javascript(if the JS engine being used has not implemented ECMAScript 5 specification, in ECMAScript 5 spec undefined
is non non-writable
, MDN DOC ),
Quote from MDN New_in_JavaScript 1.8.5 (ECMA 5) Page
Changes to global objects
Global objects made read only
The NaN, Infinity, and undefined global
objects have been made read only, per the ECMAScript 5 specification.
And from ES5 Annotated Spec
in Guthub
ES5 spec Section
x15.1.1.3
15.1.1.3 undefined
The value of undefined is undefined (see 8.1).
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
Even if global undefined
is not writable You can have a local variable named undefined
and can mess up your code(mainly comparisons with undefined
). But that's your responsibility. You can have codes like
(function(){
console.log('Second Case: ');
var undefined = 'Something';
console.log(undefined); // Will log `something`
var a ; // a is undefined
console.log(a === undefined); // false, as undefined is changed
// you might expect a === undefined will return true, but as
// `undefined` is changed it will return false.
console.log(a); // undefined
})();
Demo: http://jsfiddle.net/joycse06/V4DKN/
However if undefined
is writeable then the above assignment may hamper many comparison
made with undefined
after that line of code as undefined
is not undefined
anymore. It has some value now.
So as they are calling that anonymous function like
( window ) // one argument only
And receiving
( window, undefined) // only window is passed when calling the function
// Second argument is not passed means it's undefined
// so undefined is restored to undefined inside that function
// and no global accidental assignments can hamper jQuery's
// code using 'undefined' now
That means inside that closure undefined
is restored to undefined
, as it has not been passed any value thus securing use of undefined
inside that anonymous function.
A very good detailed article on this http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/
I am quoting some lines from the above article link to make things clear
What is undefined?
In JavaScript there is Undefined (type), undefined (value) and undefined (variable).
Undefined (type) is a built-in JavaScript type.
undefined (value) is a primitive and is the sole value of the Undefined type.
Any property that has not been assigned a value, assumes the undefined value. (ECMA 4.3.9
and 4.3.10).
A function without a return statement, or a function with an empty return statement returns undefined. The value of an unsupplied function argument is undefined.
var a;
typeof a; //"undefined"
window.b;
typeof window.b; //"undefined"
var c = (function() {})();
typeof c; //"undefined"
var d = (function(e) {return e})();
typeof d; //"undefined"
undefined (variable) is a global property whose initial value is undefined (value), Since its a global property we can also access it as a variable. For consistency I’m always going to call it a variable in this article.
typeof undefined; //"undefined"
var f = 2;
f = undefined; //re-assigning to undefined (variable)
typeof f; //"undefined"
As of ECMA 3, its value can be reassigned :
undefined = "washing machine"; //assign a string to undefined (variable)
typeof undefined //"string"
f = undefined;
typeof f; //"string"
f; //"washing machine"
Needless to say, re-assigning values to the undefined variable is very bad practice, and in fact its not allowed by ECMA 5.
Declaration function inside ( )
In your example, I see no reason for the parentheses.
For immediately invoked functions, Douglas Crockford recommends and provides a code sample as below. Source is http://javascript.crockford.com/code.html
When a function is to be invoked immediately, the entire invocation
expression should be wrapped in parens so that it is clear that the
value being produced is the result of the function and not the
function itself.
var collection = (function () {
var keys = [], values = [];
return {
get: function (key) {
var at = keys.indexOf(key);
if (at >= 0) {
return values[at];
}
},
set: function (key, value) {
var at = keys.indexOf(key);
if (at < 0) {
at = keys.length;
}
keys[at] = key;
values[at] = value;
},
remove: function (key) {
var at = keys.indexOf(key);
if (at >= 0) {
keys.splice(at, 1);
values.splice(at, 1);
}
}
};
}());
Related Topics
Calling Dynamic Function with Dynamic Number of Parameters
What's the Fastest Way to Convert String to Number in JavaScript
How to Define Custom Sort Function in JavaScript
Handling Multiple Catches in Promise Chain
Print a Div Using JavaScript in Angularjs Single Page Application
Bootstrap V2 Dropdown Navigation Not Working on Mobile Browsers
Completely Lost on How to Save Extension Popup Window Content
How to Make a Button Redirect My Page to Another Page
How to Find a User's Country Using HTML5 Geolocation
How to Swap Two Variables in JavaScript
Window.Open(Url, '_Blank'); Not Working on Imac/Safari
How to Remove One Specific Selected File from Input File Control
Testing Whether a Value Is Odd or Even
Change Form Values After Submit Button Pressed