I was having some issues in my conditions concerning undefined variables. What is, to sum it up, the best way to check if a variable is undefined?
I was mainly struggling with
x === undefined
and
typeof x === 'undefined'
You can use both ways to check if the value is undefined. However, there are little nuances you need to be aware of.
The first approach uses strict comparison === operator to compare against undefined type:
var x;
// ...
x === undefined; // true
This will work as expected only if the variable is declared but not defined, i.e. has undefined value, meaning that you have var x somewhere in your code, but the it has never been assigned a value. So it's undefined by definition.
But if variable is not declared with var keyword above code will throw reference error:
x === undefined // ReferenceError: x is not defined
In situations like these, typeof comparison is more reliable:
typeof x == 'undefined' // true
which will work properly in both cases: if variable has never been assigned a value, and if its value is actually undefined.
I guess both, depending on what you're testing? If it's a property, I'd always use x === undefined, since it's clearer (and it seems faster).
As others said, x === undefined won't work if x is not declared. Personally, I find that an even better reason to use it, since normally I shouldn't be checking if a variable is declared at all — it would usually be a sign of a coding mistake.
I've seen a lot of the other version for testing arguments — f = function(x) {if (typeof x == 'undefined') …} — if I'm code-reviewing code like this I'll tell them to change it. We know for a fact the variable is declared, and making an habit of writing it that way increases the chance you'll waste time chasing typo bugs.
The main exception is when you're trying to check if a component or library was loaded or initialized correctly. if (typeof jQuery == 'undefined') … makes sense. But in the medium term, all this should become modules anyway, in which case the typeof test should in my opinion be phased out as harmful.
(Also, personally, I prefer if (window.jQuery === undefined) for that case too. It's not portable for isomorphic code, though.)
x === undefined
does not work if variable is not declared. This returns true only if variable is declared but not defined.
Better to use
typeof x === 'undefined'
You could use any of them.
If you would like to check if a variable is undefined or null you could use:
x == null
This results in true if x is undefined or null.
Related
I've seem different approaches for (strict equality) checking for undefined:
if (something === undefined)
if (typeof something === 'undefined')
if (something === void 0)
and probably others
In a happy scenario their behavior is the same. In other words, they all work.
But, considering all the quirk corners of JavaScript, are they truly identical in behavior?
If yes, why people choose other approaches rather than the first? Is it some sort of legacy or misconception? Because the first one it's obviously the most clear in both readability and intention demonstration.
if (something === undefined) is the standard normal way
typeof something === 'undefined' on a declared variable is mostly an overdefensive solution dating from the time where you could change window.undefined. If you don't know if your variable is declared, it has the advantage of not raising an error but I don't think a legit code should support the case of a variable whose declarative state is unknown.
void 0 (or void anything) is a normalized way to get undefined so it's equivalent to the first one but useless.
Literally undefined
Test for existence, as in "variable not declared".
Same as undefined. Older version of the JS standard let you change the value of undefined as it's just a variable. void 0 is undefined, it's safer.
An extra one:
if (x == null). Tests for undefined and null because undefined == null but remember, undefined !== null
In JavaScript there's a type 'undefined' and a value undefined. The value undefined is of type 'undefined'.
I've seem different approaches for (strict equality) checking for undefined:
if (something === undefined)
if (typeof something === 'undefined')
if (something === void 0)
and probably others
In a happy scenario their behavior is the same. In other words, they all work.
But, considering all the quirk corners of JavaScript, are they truly identical in behavior?
If yes, why people choose other approaches rather than the first? Is it some sort of legacy or misconception? Because the first one it's obviously the most clear in both readability and intention demonstration.
if (something === undefined) is the standard normal way
typeof something === 'undefined' on a declared variable is mostly an overdefensive solution dating from the time where you could change window.undefined. If you don't know if your variable is declared, it has the advantage of not raising an error but I don't think a legit code should support the case of a variable whose declarative state is unknown.
void 0 (or void anything) is a normalized way to get undefined so it's equivalent to the first one but useless.
Literally undefined
Test for existence, as in "variable not declared".
Same as undefined. Older version of the JS standard let you change the value of undefined as it's just a variable. void 0 is undefined, it's safer.
An extra one:
if (x == null). Tests for undefined and null because undefined == null but remember, undefined !== null
In JavaScript there's a type 'undefined' and a value undefined. The value undefined is of type 'undefined'.
Can not quite understand the reasoning for this. In the following code the localStorage of an item is alerted as undefined, but if I use an if(x==undefined) syntax it does not work. Can somebody explain what is the problem. Thank you.
alert(localStorage["x"]);
if(localStorage["x"]=="undefined"){alert("y");}
The top line alerts undefined
The bottom line does not alert y for me.
It doesn't contain the string "undefined", it contains a value of the type undefined:
if (localStorage["x"] == undefined) { alert("y"); }
The value undefined is possible to change in older browsers, so good practice is to check the type instead:
if (typeof localStorage["x"] == 'undefined') { alert("y"); }
Try:
if(typeof( localStorage["x"]) == 'undefined'){alert("y");}
OR
if( localStorage["x"] == undefined){alert("y");}
OR
if( !localStorage["x"] ){alert("y");}
The two ways of checking for something being undefined are:
typeof foo === "undefined"
and
foo === undefined
In the first case, it will be true if foo was never defined or the value of foo is undefined.
In the second case, it will only be true if foo was defined (otherwise it'll break) and its value is undefined.
Checking its value against the string "undefined" is not the same at all!
UPDATE:
When I said that if you try to perform an operation on an object literal's property that isn't defined, I guess I meant if it's undefined at all, and what I meant was something more like this:
obj["x"].toLowerCase()
// or
obj["x"]["y"]
where you are attempting to access/operate on something that is originally undefined. In this case, simply comparing in an if statement should be fine, because of the way object literals report the value...but is very different with normal Javascript variables.
With object literals, if a key (say "x") is not defined, then
obj["x"]
returns a value of undefined, so both the typeof and basic === undefined checks will work and be true.
The whole difference of not being defined or having a value of undefined is different with normal variables.
If you had:
var a;
// or
var a = undefined;
then both the typeof and basic === undefined checks I provided earlier would work and be true. But if you never even declared a, then only the typeof check would work and be true. The === undefined check would break.
Take a look at: http://jsfiddle.net/7npJx/
If you notice in the console, it says b is not defined and breaks the if statement.
Since you're basically looking at an object literal with localStorage, the way to distinguish whether an item is not defined or has a value of undefined is to use in first. So, you could use:
if (!("x" in localStorage)) {
to check if "x" is not a defined property at all, and:
else if (localStorage["x"] === undefined) {
to then check if it is defined but has a value of undefined. Then, using:
else {
would signify that localStorage["x"] is both defined and does not have the value undefined.
In your code though, it's okay to use the typeof or in checks (based on what you want to know) because of the way object literals report properties that aren't defined. Using the basic === undefined is also okay, but as Guffa pointed out, it's possible for the actual value of undefined to be overwritten and then wouldn't work in this comparison. When it comes to normal Javascript variables, typeof and === undefined checks aren't the same.
I've been working on a javascript library, and I have a lot of redundant checks like this:
if(typeof foo !== "undefined" && foo !== null)
So, I wanted to create a function that will be a shortcut to this unwieldy check. So I came up with this:
function isset(a)
{
return (typeof a !== "undefined" && a !== null) ? true : false;
}
But, since the value could be undefined, and it attempts to use a possibly undefined variable, it turns out to be useless.
Is there a way to accomplish this without have to extend a native prototype?
It really depends on what you mean by undefined.
1. You mean the variable does not exist.
In this case, what you want is not possible. typeof is an operator and therefore has magic behavior you just can't emulate using the language. If you try to pass a variable that doesn't exist to your function, it will throw a ReferenceError.
(See below for a workaround.)
2. You mean the variable has the value undefined, but does exist.
In this case, your function will do the trick -- though it could be simplified to the following:
function isset(variable) {
return variable != null;
}
This function will return false if the variable is either undefined or null. It takes advantage of the fact that undefined == null in JavaScript. Of course, with such a short function, one could argue that the function isn't needed at all.
Recall that a variable that is declared has a value -- undefined -- by default.
The name of your function suggests you mean case #1. I don't know what sort of library you are writing, but I can't imagine a case in a library where you would need to check if a variable exists, though I can definitely think of many possibilities for case #2.
If case #1 is necessary, remember that you can re-declare variables without changing their value:
a = 1; // pretend this was set somewhere higher up in the code
var a; // this does not change the value of `a`
If you re-declare variables before you use isset, you could avoid the ReferenceError problem. You won't be able to tell if the code has already declared the variable, though; you will only be able to tell if they have not assigned it to some other value.
You can check for null and undefined at the same time by using != instead.
// checks for both null and undefined
if( foo != null ) { ...
...so no need to use a function to shorten it.
null and undefined also evaluates to false in an if statement. So the following statement also works:
if(!foo)
...
This should cut it down significantly.
I do not understand why people keep promoting if (var) or if (!var). Both fail in my browsers. Meantime if (obj.prop) passes. This means that we should use if (this.someVar) or if (window.someVar) instead of if (varbl). Ok?
The jQuery Core Style Guidelines suggest two different ways to check whether a variable is defined.
Global Variables: typeof variable === "undefined"
Local Variables: variable === undefined
Properties: object.prop === undefined
Why does jQuery use one approach for global variables and another for locals and properties?
For undeclared variables, typeof foo will return the string literal "undefined", whereas the identity check foo === undefined would trigger the error "foo is not defined".
For local variables (which you know are declared somewhere), no such error would occur, hence the identity check.
I'd stick to using typeof foo === "undefined" everywhere. That can never go wrong.
I imagine the reason why jQuery recommends the two different methods is that they define their own undefined variable within the function that jQuery code lives in, so within that function undefined is safe from tampering from outside. I would also imagine that someone somewhere has benchmarked the two different approaches and discovered that foo === undefined is faster and therefore decided it's the way to go. [UPDATE: as noted in the comments, the comparison with undefined is also slightly shorter, which could be a consideration.] However, the gain in practical situations will be utterly insignificant: this check will never, ever be any kind of bottleneck, and what you lose is significant: evaluating a property of a host object for comparison can throw an error whereas a typeof check never will.
For example, the following is used in IE for parsing XML:
var x = new ActiveXObject("Microsoft.XMLDOM");
To check whether it has a loadXML method safely:
typeof x.loadXML === "undefined"; // Returns false
On the other hand:
x.loadXML === undefined; // Throws an error
UPDATE
Another advantage of the typeof check that I forgot to mention was that it also works with undeclared variables, which the foo === undefined check does not, and in fact throws a ReferenceError. Thanks to #LinusKleen for reminding me. For example:
typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError
Bottom line: always use the typeof check.
Yet another reason for using the typeof-variant: undefined can be redefined.
undefined = "foo";
var variable = "foo";
if (variable === undefined)
console.log("eh, what?!");
The result of typeof variable cannot.
Update: note that this is not the case in ES5 there the global undefined is a non-configurable, non-writable property:
15.1.1 Value Properties of the Global Object
[...]
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 }.
But it still can be shadowed by a local variable:
(function() {
var undefined = "foo";
var variable = "foo";
if (variable === undefined)
console.log("eh, what?!");
})()
or parameter:
(function(undefined) {
var variable = "foo";
if (variable === undefined)
console.log("eh, what?!");
})("foo")
Who is interested in the performance gain of variable === undefined, may take a look here, but it seems to be a chrome optimization only.
http://jsperf.com/type-of-undefined-vs-undefined/30
http://jsperf.com/type-of-undefined-vs-undefined
Because undefined is not always declared, but jQuery declares undefined in its main function. So they use the safe undefined value internally, but outside, they use the typeof style to be safe.
For local variables, checking with localVar === undefined will work because they must have been defined somewhere within the local scope or they will not be considered local.
For variables which are not local and not defined anywhere, the check someVar === undefined will throw exception: Uncaught ReferenceError: j is not defined
Here is some code which will clarify what I am saying above. Please pay attention to inline comments for further clarity.
function f (x) {
if (x === undefined) console.log('x is undefined [x === undefined].');
else console.log('x is not undefined [x === undefined.]');
if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
else console.log('x is not undefined [typeof(x) === \'undefined\'].');
// This will throw exception because what the hell is j? It is nowhere to be found.
try
{
if (j === undefined) console.log('j is undefined [j === undefined].');
else console.log('j is not undefined [j === undefined].');
}
catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}
// However this will not throw exception
if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};
If we call the above code like this:
f();
The output would be this:
x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.
If we call the above code like these (with any value actually):
f(null);
f(1);
The output will be:
x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.
When you do the check like this: typeof x === 'undefined', you are essentially asking this: Please check if the variable x exists (has been defined) somewhere in the source code. (more or less). If you know C# or Java, this type of check is never done because if it does not exist, it will not compile.
<== Fiddle Me ==>
Summary:
When at global scope we actually want to return true if the variable is not declared or has the value undefined:
var globalVar1;
// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);
// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);
Because in global scope we are not 100% sure if a variable is declared this might give us a referenceError. When we use the typeof operator on the unknown variable we are not getting this issue when the variable is not declared:
var globalVar1;
console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');
This is due to the fact that the typeof operator returns the string undefined when a variable is not declared or currently hold the value undefined which is exactly what we want.
With local variables we don't have this problem because we know beforehand that this variable will exist. We can simply look in the respective function if the variable is present.
With object properties we don't have this problem because when we try to lookup an object property which does not exist we also get the value undefined
var obj = {};
console.log(obj.myProp === undefined);
jQuery probably expects you to be using let and const variables in functions going forward, which in JavaScript's ES6 2015 design do NOT allow you to use any local scope (function) let or const variables until they are declared. Even hoisting by Javascript does not allow you to even type-check them!
If you try and do that, JavaScript generates an error, unlike with var variables which when hoisted creates a declared but uninitialized variable you can type check or check to see if its undefined.
If you declare a let or const variable in a function, but AFTER trying to access it, typeof checks still create a Reference Error in JavaScript! Its very odd behavior, and illogical to me why it was designed that way. But that is why jQuery likely sees no use for typeof function variable use. Example:
function MyError(){
// WOW! This variable DOES NOT EVEN EXIST, but you can still check its type!
if(typeof x === 'undefined')
{
alert(1);// OK!
}
// ERROR!
// WOW! You cannot even check an existing "let" variable's TYPE in a local function!
if(typeof y === 'undefined')//REFERENCE ERROR!!
{
alert(2);
}
// We defined the variable so its hoisted to the top but in a dead zone
let y = 'test';
}
MyError();
// RESULT
// alert 1 fires but a REFERENCE ERROR is generated from the second alert 2 condition.
It is odd above how a non-existing local variable cant be checked using typeof for 'undefined', but a declared let variable in the function cannot! So this is likely why I would not depend on jQuery to define what is best. There are edge cases.
More Weirdness on "undefined" variables in JavaScript
**undefined has two different expressions, and three different uses, as follows:
"typeof" and "undefined" types : Variables that are not declared and do not exist are not assigned anything, but have a "type" of undefined. If you access a variable that does NOT even exist, much less declared or initialized, you will generate a REFERENCE ERROR if you access it, even when testing for the primitive default value of undefined which is assigned to declared variables until assigned a value. So checking the "typeof" prevents this error in this one case as follows:
// In this first test, the variable "myVariable1" does not exist yet so creates
// an error if we try and check if its assigned the default value of undefined!
if (myVariable1 === undefined) alert(true);// REFERENCE ERROR!
// Here we can elegantly catch the "undefined" type
// of the missing variable and stop the REFERENCE ERROR using "typeof".
if (typeof myVariable1 === "undefined") alert(true);// true
// Here we have declared the missing variable and notice its
// still an "undefined" type until initialized with a value.
let myVariable1;
if (typeof myVariable1 === "undefined") alert(true);// true
// Lastly, after we assign a value, the type is no longer
// "undefined" so returns false.
myVariable1 = 'hello';
if (typeof myVariable1 === "undefined") alert(true);// false
All objects and types in JavaScript that are accessed but not declared will default to a type of "undefined". So, the lesson here is try and check for the typeof first, to prevent missing variable errors!
undefined primitive values : All declared variables not yet assigned a value are assigned in JavaScript the primitve of undefined. If you have declared a variable, but not initialized it yet, its assigned this default primitive type of undefined. That is not same as an "undefined" type. The primitive value of undefined is a reserved value but can be altered, but that's not what is asked here. Notice this catches all declared but uninitialized variables only:
let myVariable3;
if (myVariable3 === undefined) alert(true);// true
let myVariable4 = 'hello';
if (myVariable4 === undefined) alert(true);// false
Objects and undefined primitives : Lastly, Object properties do NOT behave like variables in JavaScript. Object properties, when missing do not become undefined types, but are simply assigned the primitive undefined as above for undeclared variables. So they act like #2:
let myObject = {};
if (myObject.myProperty === undefined) alert(true);// true
BEST PRACTICE
Lastly....this is a VERY GOOD REASON to always check for BOTH the "undefined" type and the undefined primitive value on variables in all your JavaScript code. Most will say, you will rarely need both. There may come a day when a missing variable is accessed in a library that does not exist and creates a nasty JavaScript REFERENCE ERROR! So I always do this check, and in this order, to stop all errors in JavaScript:
if (typeof myVariable !== "undefined" && myVariable !== undefined) {
// do something safe with myVariable!
}
typeof a === 'undefined' is faster then a === 'undefined' by about 2 times on node v6.9.1.