Particularly for localStorage.foo
For Safari it is set to:
undefined
For Firefox it is set to:
null
Does anyone know the values for Chrome and IE?
Why is it different? Just random choices by browser programmers?
It's always undefined. Perhaps your observation method is what led you to believe the values are different in different browsers.
Oh, I'll qualify that statement for old versions of IE, which might do some other thing for all I know. I bet they use undefined also.
Ah - Mr. Protagonist has an interesting point. On any normal object, a non-existent property will be null. However, Firefox does indeed seem to report null as the value of a non-existent property specifically of localStorage. Hmm... My vote would be that that's a bug, but I'll check the w3c spec (or proto-spec or whatever it is).
The "value" undefined isn't really a value; it's more like the Buddhist mu — it's kinda like saying, "what you asked for doesn't make sense". The value null in JavaScript is treated differently than undefined. Thus:
var a = {};
var b = a.banana;
The variable "b" will be undefined. It's weird, but it lets you tell the difference between a property being present but null and a property being missing. (Of course, the in operator lets you figure that out too.)
Related
Common practice when checking whether a variable is undefined in JavaScript is as follows:
var isUndefined=(typeof variableName==="undefined");
I've recently come across the use of two exclamation symbols to determine the same logic:
var isUndefined=!!variableName;
Is it safe to use these methods interchangeably?Are both equally compatible across browsers?
Is there any reason why one shouldn't use the "!!" method? (It seems more concise and easy to read)
Is it safe to use these methods interchangeably?
No. Details below, but they're not interchangeable even if you remove one of the ! from your second example (with two of them, it will be true for undefined, which isn't what you seem to want from the name of the variable you're assigning to). But that's not the only issue.
Are both equally compatible across browsers?
Yes. Each of them works reliably across browsers. But see above: They reliably don't do the same thing.
Is there any reason why one shouldn't use the "!!" method?
Yes, ! (again, not !!) gives the same result for 0, NaN, null, "", and false as it does for undefined.
Details:
When you do
var isUndefined = typeof variableName==="undefined";
(the () are unnecessary), you're doing a very specific test for undefined. It will only be true for undefined.
In contrast, when you do
var isUndefined = !variableName;
you're not testing for undefined, you're testing for any falsey value. The falsey values are the ones I listed earlier (0, NaN, null, "", false, and undefined). The result will be true for any of them.
Now, if you're expecting (for instance) to get a non-null object reference or undefined, the ! test is just fine. But if you really need to know whether something is undefined, specifically, you want the typeof test.
Also, as Felix Kling pointed out in a comment on the question, the ! test will throw a ReferenceError if the variable isn't defined at all (as opposed to being defined but having the value undefined), because it tries to read the value of the variable. The typeof test is safe if you're not sure whether the variable exists at all, because it doesn't try to read its value.
I’ve been reading about undefined in JavaScript and now I am not sure if my understanding is correct. There is a lot of talk around how to check for undefined but somehow I couldn’t find any mentioning of something that to me seems fundamental to understanding of how undefined actually works (undefined being property on host object). This is the reason for this question, I need to confirm that what I understand is correct and if I’m wrong I would appreciate clarification.
Okay, first of all, undefined is property on host object (window in browsers) so it’s perfectly legal to use:
window.undefined
The value of this property is type "undefined". This is one of the JavaScript types along with Object, String, Number and Null. So if I do:
if(someVar===undefined) {}
I’m actually checking against window.undefined property, whatever it contains, is that right?
So this code below would be pretty dumb as this would check someVar only against the string "undefined", not the type nor the property of the window object, right?
if(someVar==='undefined') {}
This below would be also incorrect as this would check against the window.undefined property (whatever it contains):
if(typeof someVar===undefined) {}
So, to sum it up, the only proper and cross-browser way to check for undefined is to use typeof e.g.:
if(typeof someVar==='undefined')
Is that right?
Also in ES5 window.undefined cannot be reassigned but it’s perfectly legal in older browsers right?
This however can still be done and is evil if my understanding is right:
(function() {
var undefined=66;
alert(undefined);
})()
I would appreciate clarification if I misunderstood how undefined works in JavaScript.
You're almost correct. Except for this:
The value of [window.undefined] is type "undefined". This is one of Javascriupt types along with Object, String, Number, and Null
There are 3 undefined in javascript. The global variable undefined, the value undefined and the type undefined.
Even if the global variable undefined is overridden, the value undefined still exists. There are several ways to get it one of which is an empty argument to a function, another is a variable declaration without assigning anything:
// Note: Probably need older browsers to assign to undefined:
window.undefined = 1;
(function(foo){ // the value of foo is undefined;
var bar; // the value of bar is undefined;
return [foo === bar, foo === window.undefined]; // returns [true,false]
})();
Note carefully that in the example above we're checking the value, not the type. Yes === checks type and value but if you replace === with == the result would be the same.
The value undefined has type undefined ('Undefined' in the spec and documentation but typeof returns 'undefined') and type undefined is only valid for the value undefined.
That's all fine, plus:
you can use void 0 to reliably "generate" the real undefined value (or not-a-value; it's kind-of zen)
in a function, you can reference an argument that you know isn't supplied to get a reliable undefined
(function( undefined ) {
// ...
})();
This second example is not really the clearest code in the world, but you'll see it sometimes in common public codebases, tutorials, etc.
So if I do:
if(someVar===undefined) {}
I'm actually checking against window.undefined property whatever it
contains is that right?
Right.
So this code below would be pretty dumb as this would check someVar
only against the string undefined, not the type nor the property of
window object right?
if(someVar==='undefined') {}
Right.
This below would be also incorrect as this would check against the
window.undefined property (whatever it contains):
if(typeof someVar===undefined) {}
Right.
So to sum it up, the only proper and cross-browser way to check for
undefined is to use typeof e.g.:
if(typeof someVar==='undefined')
Is that right?
Yes, though it is error-prone because you may mis-type that string and get no error (even in strict mode) to indicate the mistake.
So it's better to call some method, especially if you're already using some framework e.g. in AngularJS - angular.isUndefined
Also in ES5 window.undefined cannot be reassigned but its perfectly legal in older browsers right?
Right.
This however can still be done and is evil if I my understanding is
right:
(function() {
var undefined=66;
alert(undefined);
})()
I believe so.
So to sum it up, the only proper and cross-browser way to check for undefined is to use typeof e.g.:
if(typeof someVar==='undefined')
No, the direct comparison somevar === undefined is fine.
There are any number of global variables that can be overwritten or shadowed that will break code. There's no way to protect against them all, except to simply not allow bad code.
What's nice about the direct comparison (aside from being shorter and cleaner) is that it's must more natural and intuitive, whereas people often get the other syntax wrong. They end up accidentally using the other examples you gave:
if (somevar === 'undefined')
if (typeof somevar === undefined)
These are very common errors, and are much more common than people redefining undefined.
Furthermore, you'll see things like this:
if (typeof somevar === 'undefiend')
This is much more subtle, and is hard to spot when surrounded by a bunch of other code. Again, it's a common mistake.
Probably the worst is when you see this:
if (typeof somevar === 'undefined')
somevar = "foobar";
What's wrong with that? Well, if somevar had not been declared, we've now created an implicit global variable. This can be really bad. If we had done a simple comparison, we would have been alerted to the problem with a ReferenceError.
like
function myFunction(){
var undefined = "abc";
}
If its possible then how to restrict not to allow that?
Is it possible to overwrite the undefined in javascript?
If by "the undefined" you mean the global undefined variable, then no. Since EcmaScript 5, it is specified as non-writable. However, older browsers don't adhere that spec, so it is overwritable in legacy engines. You cannot really prevent it in them, but always reset it by undefined = void 0;. If you still worry and want to know how to protect your own scripts, check the question How dangerous is it in JavaScript, really, to assume undefined is not overwritten?.
like function myFunction(){ var undefined = "abc"; }
That's a different thing. You can always declare a local variable with the name undefined (shadowing the global one) and assign arbitrary values to it.
Some browsers allow it, the best way to restrict it is avoiding it.
But... some are using this technique to preserve the undefined:
(function(undefined){
})()
They get a variable called undefined but don't pass a value which gives undefined the undefined value.
From jQuery's source code:
(function( window, undefined ) {
...
...
})(window);
Yes it is possible to overwrite undefined.
This question has good solutions for working around that problem - How to check for "undefined" in JavaScript?
It's possible to set the individual elements of a function arguments property (what Mozilla calls an 'array-like' property), however Mozilla reports it is not possible to add elements to this property in SpiderMonkey 1.5 though this is fixed in 1.6 (ref. the note on SpiderMonkey here... https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments).
This is a useful property, chaining constructors from subclasses, creating a list of arguments to pass to a function (e.g., myclassmethod.apply(this, arguments)), etc.
However I've found V8 will not extend the length in the same way Mozilla reports of SpiderMonkey 1.5. (Not sure what the status is with other JavaScript engines, Opera, Rhino, etc.).
Is this actually an ECMA feature? Has Mozilla got it wrong in considering this a bug, or does V8 have a bug to fix?
[Update] I've found using V8 that the arguments.length property can be assigned to, and so effectively arguments can be extended (or set to whatever length you require otherwise). However JSLint does complain this is a bad assignment.
[Update] Some test code if anyone wants to try this in Opera, FF etc., create an instance of a subclass calling the constructor with one arg while adding an element to arguments in the subclass constructor and calling the superclass constructor, the superclass should report two arguments:
function MyClass() {
if (arguments.length) {
console.log("arguments.length === " + arguments.length);
console.log("arguments[0] === " + arguments[0]);
console.log("arguments[1] === " + arguments[1]);
}
}
function MySubClass() {
console.log(arguments.length);
//arguments.length = 2; // uncomment to test extending `length' property works
arguments[1] = 2;
MyClass.apply(this, arguments);
}
MySubClass.prototype = new MyClass();
new MySubClass(1);
[Update] JSLint actually complains when you make any kind of assignment to arguments by the looks (e.g., arguments[0] = "foo"). So maybe JSLint has some work to do here also.
Not sure if this is what you are looking for, but you can make the arguments object into a standard array:
var args = [].slice.call(arguments, 0);
[EDIT] so you could do:
myclassmethod.apply(this, [].slice.call(arguments, 0).push(newValue));
ECMA-262 10.1.8 says that the prototype of the arguments object is the Object prototype and that the arguments object is initialized in a certain way, using the phrase "initial value". So, it would seem like you could assign any of its properties to whatever you want. I'm not sure if that's the correct interpretation though.
OK, I think we can conclude on this one.
Running the above example code on FF, Comodo Dragon, Opera and IE (all current version, Windoze) they will all accept a change of the arguments.length property to resize the (as Mozilla phrases this, 'array-like') arguemnts object. None will increase the size by assigning a value as is usual for an array (i.e., arguments[arguments.length] = "new arg").
It seems the consensus of the javascript engines is that as an 'array-like' object arguments behaves like an array, but is otherwise inclined to throw a few surprises ;) Either way the interpretation of the ECMA standard appears to be on the face of it at least consistent across the board, and so the semantics are not really an issue (the whys and wherefores being the only remaining question but of historical interest only).
Neither MSDN nor Mozilla seem to have this documented (not sure where V8 or Opera hide their JS docs) - in a nutshell to conclude some documentation would definitely not go amiss. At which point I will bow out, however if someone could opportunistically drop the hint to the relevant parties at some point it is a useful technique to use once in a while.
Thanks for all who have taken the time to look at this question.
[Update] BishopZ has pointed out above that .apply will take an array of arguments anyway (this has slipped my mind since I last used it many years ago, and which solves my problem). However the 'array-like' arguments can still be used, and might even be preferable in some situations (easier for example to pop a value onto, or just to pass on arguments to a superclass). Thanks again for looking at the issue.
Every time anyone mentions testing against undefined, it's pointed out that undefined is not a keyword so it could be set to "hello", so you should use typeof x == "undefined" instead. This seems ridiculous to me. Nobody would ever do that, and if they did it would be reason enough to never use any code they wrote... right?
I found one example of someone who accidentally set undefined to null, and this was given as a reason to avoid assuming that undefined isn't overwritten. But if they'd done that, the bug would have gone undetected, and I fail to see how that's better.
In C++ everyone is well aware that it's legal to say #define true false, but nobody ever advises you avoid true and use 0 == 0 instead. You just assume that nobody would ever be a big enough jerk to do that, and if they do, never trust their code again.
Has this ever actually bitten somebody where someone else assigned to undefined (on purpose) and it broke your code, or is this more of a hypothetical threat? I'm willing to take my chances to make my code marginally more readable. Is this a really bad idea?
To reiterate, I am not asking for how to protect against reassigned undefined. I've seen those tricks written 100 times already. I'm asking how dangerous it is to not use those tricks.
No, I never have. This is mostly because I develop on modern browsers, which are mostly ECMAScript 5 compliant. The ES5 standard dictates that undefined is now readonly. If you use strict mode (you should), an error will be thrown if you accidentally try to modify it.
undefined = 5;
alert(undefined); // still undefined
'use strict';
undefined = 5; // throws TypeError
What you should not do is create your own scoped, mutable undefined:
(function (undefined) {
// don't do this, because now `undefined` can be changed
undefined = 5;
})();
Constant is fine. Still unnecessary, but fine.
(function () {
const undefined = void 0;
})();
No proper code will do such a thing. But you can never know what some wannabe-smart developer or a plugin/library/script you are using did. On the other side, it's extremely unlikely and modern browsers will not allow overwriting undefined at all, so if you are using such a browser for development you'll quickly notice if any code tries to overwrite it.
And even though you did not ask for it - many people will probably find this question when looking for the more common "how to protect against redefined undefined" issue, so I'll answer that anyway:
There's a very good way to get a truly undefined undefined no matter how old the browser is:
(function(undefined) {
// your code where undefined is undefined
})();
This works because an argument that is not specified is always undefined. You can also do it with a function that accepts some real arguments, e.g. like this when you are using jQuery. It's usually a good idea to ensure a sane environment in this way:
(function($, window, undefined) {
// your code where undefined is undefined
})(jQuery, this);
Then you can be sure that inside that anonymous function the following things are true:
$ === jQuery
window === [the global object]
undefined === [undefined].
However, note that sometimes typeof x === 'undefined' is actually necessary: If the variable x has never been set to a value (contrary to being set to undefined), reading x in a different way such as if(x === undefined) will throw an error. This does not apply to object properties though, so if you know that y is always an object, if(y.x === undefined) is perfectly safe.
There's a simple solution to that: compare against void 0 which is always undefined.
Note that you should avoid == as it may coerce the values. Use === (and !==) instead.
That said, the undefined variable may be set by error if someone writes = instead of == when comparing something against undefined.
Only you know what code you use, and therefore how dangerous it is. This question can't be answered in the way you've clarified you want it answered.
1) Create a team policy, disallow redefining undefined, reserving it for its more popular usage. Scan your existing code for undefined left assignment.
2) If you don't control all the scenarios, if your code is used outside situations you or your policies control, then obviously your answer is different. Scan the code that does use your scripts. Heck, scan web for statistics of undefined left assignment if you wish, but I doubt that's been done for you, because it's easier to just pursue answer #1 or #3 here instead.
3) And if that answer isn't good enough, it's probably because, again, you require a different answer. Maybe you are writing a popular library that will be used inside corporate firewalls, and you don't have access to the calling code. Then use one of the other fine answers here. Note the popular jQuery library practices sound encapsulation, and begins:
(function( window, undefined ) {
Only you can answer your question in the specific way you seek. What more is there to say?
edit: p.s. if you really want my opinion, I'll tell you it's not dangerous at all. Anything that would be so likely to cause defects (such as assigning to undefined, which is obviously a well-documented risky behaviour) is itself a defect. It's the defect that is the risk. But that's just in my scenarios, where I can afford to hold that perspective. As I'd recommend you do, I answered the question for my use-cases.
It's safe to test against undefined. As you already mention. If you get to some code that overrides it (which is highly improvable), just don't use it anymore.
Maybe if you are creating a library for public use, you can use some of the techniques to avoid the user change it. But even in this case, it's their problem, not your library.
You can use undefined in your code when coding for browsers supporting ECMAScript 5.1 as it is immutable according to the language specification.
Also see this compatibility table or this caniuse ECMAScript 5 to see that all modern browsers (IE 9+) have implemented immutable undefined.
It's not dangerous at all. It can only be overwritten when running on an ES3 engine and that's not likely to be used any more.
First of all, if your code breaks it's probably not because some other developer out there "is trying to be a jerk" as you put it.
It's true that undefined is not a keyword. But it is a global level primitive. It was intended to be used like this (see "undefined" at developer.mozilla.org):
var x;
if (x === undefined) {
// these statements execute
}
else {
// these statements do not execute
}
The common alternative to that (also from MDN) and in my opinion the better way is:
// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
// these statements execute
}
if(x === undefined){ // throws a ReferenceError
}
Which has a couple of advantages, the obvious one (from the comments) is that it does not trigger an exception when x is not declared. It's also worth noting that MDN also points out that it is important to use === over == in the first case because:
var x=null;
if (x === undefined) {
// this is probably what you meant to do
// these lines will not execute in this case
}
else if (x == undefined) {
// these statements will execute even though x *is* defined (as null)
}
else {
// these statements do not execute
}
This is another often overlooked reason why it is probably better to just use the second alternative in all cases.
Conclusion: It's not wrong to code it the first way, and certainly not dangerous. The argument you've seen that you use as an example against it (that it can be overwritten) is not the strongest argument for coding the alternative with typeof. But using typeof is stronger for one reason specifically: it doesn't throw an exception when your var is not declared. It could also be argued that using == instead of === is a common mistake in which case it's not doing what you expected it to. So why not use typeof?