I have noticed jQuery and related keynote plugins like jQuery.UI pass undefined as a parameter into anonymous functions used in their module definitions, like so:
(function($, undefined) { ... })(jQuery);
Alternatively, I have noticed other plugins recommended by jQuery and/or others do NOT pass undefined in as a parameter.
This is probably a silly question, but...
Shouldn't it always be available anyway? Why pass it in? Is there some sort of other purpose or trick going on here?
There are two reasons for that:
1) If undefined is a variable in the function scope rather than a global object property, minifiers can reduce it to a single letter thus achieving a better compression rate.
2) Before ES5*, undefined was a property of the global object without write-protection. So it could be overwritten, resulting in strange and unexpected behavior. You could do something like this:
var test = 123;
undefined = 123;
if (test === undefined){
// this will actually be true, since undefined now equals 123
}
By having an function argument undefined (the name actually does not matter) which you don't pass a parameter to, you could make sure you have a variable which really is undefined so you can test "undefinedness" against this variable.
Btw. the safest method to test for undefined is: typeof ( var ) === 'undefined'
(*) With EcmaScript 5, the global properties undefined, NaN and Infinity became readonly. So with its general adoption in all modern browsers - of course with the exception of IE 9 - overwriting those values was not possible anymore.
That is done to make sure that undefined always is undefined. In older versions of the ECMAScript spec (prior to ECMAScript 5), undefined wasn't a reserved word but a regular variable. In older browsers this would be allowed for instance:
undefined = 2; // Assign a different value to undefined
// Now this statement would be true
if (undefined == 2)
So to make sure that undefined is in fact undefined, even if some other "evil" script would have reassigned undefined with another value, you create a parameter that you call undefined, and then when you call the function, you make sure to not pass a value to that parameter - thus you can be sure that the variable undefined will always be undefined within your function.
So in the case of jQuery:
(function($, undefined) { ... })(jQuery);
They pass in jQuery and assign it to the $ variable for convenience, but then they don't pass a second value to the undefined parameter, thus undefined will be undefined.
Modern browsers
In modern browsers, undefined is a non-configurable, non-writable property per the ECMAScript 5 specification.
undefined is not a reserved word in javascript, it is simply a variable. jQuery is ensuring that if some bad developer overwrites the value of undefined in their javascript, then jQuery will ignore it and establish it's own variable, undefined, which is never passed a value (see the self-executing (jQuery) at the end) and is therefore actually undefined.
Related
Having the follwoing 2 patterns to generate a reliable local variable with the name undefined that should contains undefined is any of the 2 patterns safer (less error-prone / breakable) than the other?
pattern1
function(arg1,arg2,....,undefined)
{
}
pattern2
function(arg1,arg2,....)
{
var undefined;
}
Maybe I am just to worried, but the pattern1 type seems breakable by simply passing a variable to the function which then is assigned to the local variable undefined.
PS:
Also it seems newer browsers (i.e. FF 33 / Chromium 37) do not allow this pitfall anymore
window.undefined = "omg";
"omg" == undefined; //true
indeed they produce this
window.undefined = "omg";
console.log(window.undefined); // logs undefined and NOT "omg" in FF33/Chromium 37
hence making the safety patterns superflous anyway.
To me it seems agreeable that window.undefined may never be reset (readonly and being undefined) and in effect I wonder why there has anyway been a browser implementation which allowed for this being-a-bug-only-feature (at least I cannot see a use-case)?
Maybe I am just to worried, but the pattern1 type seems breakable by simply passing a variable to the function
Yes, and that is why this pattern is only used in IEFEs where you yourself are the only caller of that function:
(function(arg1, arg2, …, undefined) {
// …
}(val1, val2, …));
Also it seems newer browsers do not allow this pitfall anymore
Yes, all engines that implement ECMAScript 5 don't allow this - the global undefined variable is non-writable just as you described.
hence making the safety patterns superflous anyway
Indeed, using it feels a lot like cargo-cult programming. Everyone expects ES5 today anyway.
I wonder why there has anyway been a browser implementation which allowed for this being-a-bug-only-feature (at least I cannot see a use-case)?
It was simply a lack in the ES 3 spec. This never has been a "feature", it simply had been forgotten to be specified.
Both pattern will essentially produce the same effect and its third party library/framework which adopted this approach to minimize the accidental redifinition of undefined.
undefined is a property of the global object, i.e. it is a variable in global scope. The initial value of undefined is the primitive value undefined.
Prior to ECMAScript 5/modern browsers anyone could configure/rewrite this variable to any value. This posed a problem with third part libraries/frameworks where
undefined = 5;//now undefined is of type number
//code inside library
(function (arg1){
if(somevar === undefined){//unintentionally it will compare somevar to 5
}
})(arg1);
Thus to minimize the effect from global variables they adopted below approach
(function (arg1, undefined){//since only one param is passed the second param undefined would indeed will be of type undefined
if(somevar === undefined){//it will compare somevar to undefined
}
})(arg1);
The first pattern you provided is incomplete. It's proper use is when creating inline closure, so that you ensure the correct value of undefined by not passing any value for the last argument to the closure function.
(function (undefined) {
// ... your safe code here
})();
Then it is equal in consequences to the second pattern. However, the first pattern is usually the one that is used, because enclosing all your code in a closure is a good idea under any circumstances (to avoid leaking variables into global scope).
In JavaScript undefined is not a keyword, it is a variable. Sort of special variable. This is known to cause trouble because undefined could be reassigned. I do not really know why would anyone want to do that, but this is possible, and maybe you can experience this by using one of those genius frameworks out there, see the code:
function f() {
var z, undefined = 42
console.log(z, undefined, z == undefined)
} f()
Outputs:
undefined 42 false
Now how does one protect himself from such a confusion? Should one just cross his fingers that undefined is undefined?
Just use void 0, it's simply bulletproof. And it's a keyword too.
You can pass undefined as a function parameter, this will ensure that undefined is undefined in the scope of the function.
Many JavaScript libraries use this technique, for example look at jQuery source code
//jQuery
(function( window, undefined ) {
...
})( window );
Because the function expects two formal parameters, but we only give it one, the other gets the (true) value undefined, and then we can rely on that within the function.
one possibility is to check the type of the variable instead of checking equality to undefied:
if (typeof(VARIABLE) != "undefined")
or read on here: How to check for “undefined” in JavaScript?.
As you see,undefined is not a keyword in javascript(Is it right?).So we can use it as a variable though I'm sure this is a bad idea.Now my question is why I can't give a value to undefined.
Code:
var undefined=3;
undefined;//still undefined
Any suggestions will be thankfull.
Because in older environments(before JS 1.8.5) it was possible to change the value of undefined, and checking for something that didn't exist was made in a way that was possible to break. It is a common choice to develop libraries inside their own closures, using the IIFE pattern to create a variable undefined which is not touched from external code(jQuery for example, and most libraries), this is an example:
(function(undefined) {
//code which safely uses undefined
})();
Note that there is a parameter called undefined and the IIFE is invoked without any parameter, making that undefined effectively become undefined. In newer environments it is not possible to change the value of undefined, but for retrocompatibility it is yet used a lot.
Yet the safest way to check for an undefined type is to use typeof. Its usage, in fact, cannot be overridden in any way, and it can be used safely: typeof foo == 'undefined'.
Remember that there is a slight difference between undefined and undeclared:
var x; //declared but undefined
x === undefined; //true
But in older environments you were able to do
var undefined = 1;
var x; //declared, of type undefined, but...
x === undefined // false, because undefined is 1 and x is of type undefined
As I said before, the safest way to check for an undefined variable(being sure it will work in older environments) is to use typeof:
var undefined = 1;
var x;
typeof x == 'undefined'; //true
Remember also that using equality check(==) with undefined also checks for null(in fact, undefined == null but undefined !== null), so I recommend using strictly equality operator(===), which checks only for undefined.
According to the MDN, undefined became non-writable, starting in JavaScript 1.8.5.
That yields that it was fully "legal" to use it as a variable until then.
But it obviously isn't a good idea.
See a full explanation (I'm not the author) of how 'undefined' is used in JavaScript here http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/
Compared to other languages, JavaScript’s concept of undefined is a
little confusing. In particular, trying to understand ReferenceErrors
(“x is not defined”) and how best to code against them can be
frustrating.
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.
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.
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 (though amongst
the current set of full browser releases, only Safari enforces this).
It's been a while since ECMAScript 5 came out and is being supported quite well in most modern browsers (IE9, CH 19+, FF 4+) and with it so is the "Immutable undefined". Though I keep seeing "undefined" being passed like so:
(function ( ..., undefined ) {
})(...);
From what I can tell Crockford's JSLint tool doesn't really like it:
Expected an identifier and instead saw 'undefined' (a reserved word).
Even though it's not being passed (there's no argument on the function call) and it's really an identifier. I understand that his tool isn't a bible we should follow to the death and on the other hand JSHint doesn't seem to care about it.
Is this still considered a best practice today and how does it affect code performance/security? Considering browser support >= IE9.
Is this still considered a best practice today and how does it affect code performance/security? Considering browser support >= IE9.
Much like undefined, Infinity is a non-writable property of the global object rather than a literal like null, so it can be used as a parameter name without raising an error. Lets consider a function like this
function example(Infinity) {
return Infinity;
}
In example, Infinity is no longer a non-writable property and instead acts like any other parameter to a function, initialised as undefined if nothing is passed or otherwise taking the value of the argument. This means in this function you can't just assume Infinity will mean Infinity, because it doesn't, but you could assume it will mean undefined.
So let's go back to the question of undefined. It will be initialised as undefined so the meaning will stay the same, however, it has now lost it's immutability within the function and therefore any typos assinging a values to undefined will have this error carried forward. Additionally, if a parameter is passed to the function the value will be different from the start.
Therefore to conclude, it does have an effect on security, as an undefined like this is no longer as "safe" because it has lost it's immutable status and can be changed.
It may be interesting to note that undefined is not actually a reserved word. If you require an undefined for compatibility, rather than adding it as a parameter name, I would suggest using a simple var undefined; at the top of the function or in the global namespace where you will find var undefined; undefined = 1; undefined; // undefined where it is immutable.
If you wanted to comply with jsLint, you could use another variable that is not a reserved word instead of undefined. The following complies with jsLint:
(function (window, document, undef) {
'use strict';
}(window, document));
You would, however, need to remember to use your newly defined variable (in this case undef instead of undefined). The strict mode above was added to comply with jsLint. This is mostly used so that you know for certain that the variable you are testing to be undefined is actually undefined.
Note, that if you're running this example in the text area provided on the jsLint website, you may need to define window and document. I was receiving two errors until I did so.
var window = window; //global window object
var document = document; //global window object
However, I'm of the opinion that:
(function (..., undefined) {
'use strict';
}(...));
is perfectly fine and more importantly, highly recommended.
There are cases where reserved words can be changed from their normal states. Such as setting undefined to true. Paul Irish discusses this briefly in his video: http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source/
I have seen different code examples with variables declared and set to undefined and null. Such as:
var a; // undefined - unintentional value, object of type 'undefined'
var b = null; // null - deliberate non-value, object of type 'object'
If the code to follow these declarations assigns a value to a or to b, what is the reason for using one type of declaration over another?
The first example doesn't assign anything to the variable, so it implicitly refers to the undefined value (see 10.5 in the spec for the details). It is commonly used when declaring variables for later use. There is no need to explicitly assign anything to them before necessary.
The second example is explicitly assigned null (which is actually of type null, but due to a quirk of the JavaScript specification, claims to have type "object"). It is commonly used to clear a value already stored in an existing variable. It could be seen as more robust to use null when clearing the value since it is possible to overwrite undefined, and in that situation assiging undefined would result in unexpected behaviour.
As an aside, that quirk of null is a good reason to use a more robust form of type checking:
Object.prototype.toString.call(null); // Returns "[object Null]"
I just saw this link which clarified my question.
What reason is there to use null instead of undefined in JavaScript?
Javascript for Web Developers states "When defining a variable that is meant to later hold an object, it is advisable to initialize the variable to null as opposed to anything else. That way, you can explicitly check for the value null to determine if the variable has been filled with an object reference at a later time."
I don't think there's a particular better way of doing things, but I'm inclined to avoid undefined as much as possible. Maybe it's due to a strong OOP background.
When I try to mimic OOP with Javascript, I would generally declare and initialize explicitly my variables to null (as do OOP languages when you declare an instance variable without explicitly initializing it).
If I'm not going to initialize them, why even declare them in the first place? When you debug, if you haven't set a value for a variable you watch, you will see it as undefined whether you declared it or not...
I prefer keeping undefined for specific behaviours:
when you call a method, any argument you don't provide would have an undefined value. Good way of having an optional argument, implementing a specific behaviour if the argument is not defined.
lazy init... in my book undefined means "not initialized: go fetch the value", and null means "initialized but the value was null (eg maybe there was a server error?)"
arrays: myArray[myKey] === null if there is a null value for this key, undefined if a value has never been set for this key.
Be careful though, that myVar == null and myVar == undefined return the same value whether myVar is undefined, null or something else. Use === if you want to know if a variable is undefined.
I would explicitly choose null, to not create an object whose id is later overwritten anyway:
var foo = {}; // empty object, has id etc.
var foo2 = null; // good practice, // filled with an object reference at a later time
var foo3;// undefined, I would avoid it
console.log(typeof foo);
console.log(typeof foo2);
console.log(typeof foo3);
Setting null also ensures good readability to identify the datatype (object),
results in
object
object
undefined
Source (Professional JavaScript for Web Developers 3rd Edition):
When defining a variable that is meant to later hold an object, it is
advisable to initialize the variable to null as opposed to anything
else. That way, you can explicitly check for the value null to
determine if the variable has been filled with an object reference at
a later time, such as in this example:
if (foo2 != null){
//do something with foo2
}
The value undefined is a derivative of null, so ECMA-262 defines them to be superficially equal as follows:
console.log(null == undefined); // prints true
console.log(null === undefined);// prints false
null is an object.. When something is undefined it is nothing.. it is not an object, neither a string, because it hasn't been defined yet.. obviously.. then it is simply a property with no function..
example:
You declare a variable with var but never set it.
var foo;
alert(foo); //undefined.
You attempt to access a property on an object you've never set.
var foo = {};
alert(foo.bar); //undefined
You attempt to access an argument that was never provided.
function myFunction (foo) {
alert(foo); //undefined.
}