Although there are semantic differences between JavaScript's null and undefined, many times they can be treated as the same. What's the preferable way of checking if the value is either null or undefined?
Right now I'm doing the following:
if (typeof value === "undefined" || value === null) {
// do something
}
Which is pretty verbose. I could, of course, create a function for this and import everywhere, but I'm wishing that there's a better way to achieve this.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
No, it gets the job done 100% of the time. The only values that are == null are null and undefined. 0 == null is false. "" == undefined is false. false == null is false. Etc. You're confusing == null with falsiness, which is a very different thing.
That's not to say, though, that it's a good idea to write code expecting everyone to know that. You have a perfectly good, clear check in the code you're already using. Whether you choose to write value == null or the explicit one you're currently using (or if (value === undefined || value === null)) is a matter of style and in-house convention. But value == null does do what you've asked: Checks that value is null or undefined.
The details of == are here: Abstract Equality Comparison.
underscore js has a function for this _.isUndefined()
from https://underscorejs.org/#isUndefined
isUndefined _.isUndefined(value)
Returns true if value is undefined.
example:
_.isUndefined(window.missingVariable);
=> true
lodash has a similar function. see https://lodash.com/docs/4.17.11#isUndefined
Both have similar functions for isNull too.
I find the functions are useful for others to know what is being tested for.
Related
Although there are semantic differences between JavaScript's null and undefined, many times they can be treated as the same. What's the preferable way of checking if the value is either null or undefined?
Right now I'm doing the following:
if (typeof value === "undefined" || value === null) {
// do something
}
Which is pretty verbose. I could, of course, create a function for this and import everywhere, but I'm wishing that there's a better way to achieve this.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
Also, I know that
if (value == null) {
}
Will get the job done 90% of the time, unless value is zero... or false... or a number of implicit things that can cause obscure bugs.
No, it gets the job done 100% of the time. The only values that are == null are null and undefined. 0 == null is false. "" == undefined is false. false == null is false. Etc. You're confusing == null with falsiness, which is a very different thing.
That's not to say, though, that it's a good idea to write code expecting everyone to know that. You have a perfectly good, clear check in the code you're already using. Whether you choose to write value == null or the explicit one you're currently using (or if (value === undefined || value === null)) is a matter of style and in-house convention. But value == null does do what you've asked: Checks that value is null or undefined.
The details of == are here: Abstract Equality Comparison.
underscore js has a function for this _.isUndefined()
from https://underscorejs.org/#isUndefined
isUndefined _.isUndefined(value)
Returns true if value is undefined.
example:
_.isUndefined(window.missingVariable);
=> true
lodash has a similar function. see https://lodash.com/docs/4.17.11#isUndefined
Both have similar functions for isNull too.
I find the functions are useful for others to know what is being tested for.
I want to check this:
if ( typeof myVar != "undefined" && myVar != null )
...
In other words, I want to check if a variable has a defined value (including 0 or an empty string), but not undefined or null, which I interpret as valueless.
Do I have to do the two-part check each time or is there a handy shortcut?
If you want to allow 0 and "" as valid values and you want to cover the case of the variable might not even be delcared, but don't consider null a valid value, then you have to specifically check for undefined and null like this:
if (typeof myVar !== 'undefined' && myVar !== null)
...
A lot of values are falsey (they don't satisfy if (myVar) so you really have to conciously decide which ones you're testing for. All of these are falsey:
undefined
false
0
""
null
NaN
If you want to allow some, but not others, then you have to do a more specific test than if (myVar) like I've shown above to isolate just the values you care about.
Here's a good writeup on falsey values: http://www.sitepoint.com/javascript-truthy-falsy/.
If you know the variable has been declared and you just want to see if it's been initialized with something other than null, you can use this:
if (myVar != undefined)
...
Using only the != instead of !== allows this to test for both undefined and null via type conversion. Although, I wouldn't recommend this because if you're trying to discern between falsey values, it's probably better to NOT let the JS engine do any type conversions at all so you can control exactly what it does without having to memorize all the type conversion equality rules. I'd stick with this to be more explicit:
if (typeof myVar !== 'undefined' && myVar !== null)
...
If you want to know if it has any non-falsey value, you can of course do this (but that won't allow 0 or "" as valid values:
if (myVar)
...
The 2-part method. If you don't check for the typeof first, you'll end up with a reference error.
If you know the context of myVar, you should be able to do this:
if (this.myVar != null) {
...
}
if myvar could be undefined, calling it without the typeof check will throw an error.
And if it is defined as null (like myvar= element.lastChild for an element with no children) you will miss catching it if you just use typeof.
Well, null is a defined value... so if you want to make sure that the variable doesn't contain null, and isn't undefined you must do both checks.
[Bounty Edit]
I'm looking for a good explanation when you should set/use null or undefined and where you need to check for it. Basically what are common practices for these two and is really possible to treat them separately in generic maintainable codee?
When can I safely check for === null, safely check for === undefined and when do I need to check for both with == null
When should you use the keyword undefined and when should one use the keyword null
I have various checks in the format of
if (someObj == null) or if (someObj != null) which check for both null and undefined. I would like to change all these to either === undefined or === null but I'm not sure how to guarantee that it will only ever be one of the two but not both.
Where should you use checks for null and where should you use checks for undefined
A concrete example:
var List = []; // ordered list contains data at odd indexes.
var getObject = function(id) {
for (var i = 0; i < List.length; i++) {
if (List[i] == null) continue;
if (id === List[i].getId()) {
return List[i];
}
}
return null;
}
var deleteObject = function(id) {
var index = getIndex(id) // pretty obvouis function
// List[index] = null; // should I set it to null?
delete List[index]; // should I set it to undefined?
}
This is just one example of where I can use both null or undefined and I don't know which is correct.
Are there any cases where you must check for both null and undefined because you have no choice?
Functions implicitly return undefined. Undefined keys in arrays are undefined. Undefined attributes in objects are undefined.
function foo () {
};
var bar = [];
var baz = {};
//foo() === undefined && bar[100] === undefined && baz.something === undefined
document.getElementById returns null if no elements are found.
var el = document.getElementById("foo");
// el === null || el instanceof HTMLElement
You should never have to check for undefined or null (unless you're aggregating data from both a source that may return null, and a source which may return undefined).
I recommend you avoid null; use undefined.
Some DOM methods return null. All properties of an object that have not been set return undefined when you attempt to access them, including properties of an Array. A function with no return statement implicitly returns undefined.
I would suggest making sure you know exactly what values are possible for the variable or property you're testing and testing for these values explicitly and with confidence. For testing null, use foo === null. For testing for undefined, I would recommend using typeof foo == "undefined" in most situations, because undefined (unlike null) is not a reserved word and is instead a simple property of the global object that may be altered, and also for other reasons I wrote about recently here: variable === undefined vs. typeof variable === "undefined"
The difference between null and undefined is that null is itself a value and has to be assigned. It's not the default. A brand new variable with no value assigned to it is undefined.
var x;
// value undefined - NOT null.
x = null;
// value null - NOT undefined.
I think it's interesting to note that, when Windows was first written, it didn't do a lot of checks for invalid/NULL pointers. Afterall, no programmer would be dumb enough to pass NULL where a valid string was needed. And testing for NULL just makes the code larger and slower.
The result was that many UAEs were due to errors in client programs, but all the heat went to Microsoft. Since then, Microsoft has changed Windows to pretty much check every argument for NULL.
I think the lesson is that, unless you are really sure an argument will always be valid, it's probably worth verifying that it is. Of course, Windows is used by a lot of programmers while your function may only be used by you. So that certainly factors in regarding how likely an invalid argument is.
In languages like C and C++, you can use ASSERTs and I use them ALL the time when using these languages. These are statements that verify certain conditions that you never expect to happen. During debugging, you can test that, in fact, they never do. Then when you do a release build these statements are not included in the compiled code. In some ways, this seems like the best of both worlds to me.
If you call a function with no explicit return then it implicitly returns undefined. So if I have a function that needs to say that it did its task and there is nothing result, e.g. a XMLHTTPRequest that returned nothing when you normally expect that there would be something (like a database call), then I would explicitly return null.
Undefined is different from null when using !== but not when using the weaker != because JavaScript does some implicit casting in this case.
The main difference between null and undefined is that undefined can also mean something which has not been assigned to.
undefined false
(SomeObject.foo) false false
(SomeObject.foo != null) false true
(SomeObject.foo !== null) true true
(SomeObject.foo != false) true false
(SomeObject.foo !== false) true false
This is taken from this weblog
The problem is that you claim to see the difference, but you don't. Take your example. It should really be:
var List = []; // ordered list contains data at odd indexes.
var getObject = function(id) {
for (var i = 1; i < List.length; i+=2) {
if (id === List[i].getId()) {
return List[i];
}
}
// returns undefined by default
}
Your algorithm is flawed because you check even indexes (even though you know there's nothing there), and you also misuse null as a return value.
These kind of functions should really return undefined because it means: there's no such data
And there you are in the heart of the problem. If you don't fully understand null and undefined and may use them wrongly sometimes, how can you be so sure that others will use it correctly? You can't.
Then there are Host objects with their nasty behavior, if you ask me, you better off checking for both. It doesn't hurt, in fact, it saves you some headaches dealing with third party code, or the aformentioned non-native objects.
Except for these two cases, in your own code, you can do what #bobince said:
Keep undefined as a special value for signalling when other languages might throw an exception instead.
When to set/use them...
Note that a method without a return statement returns undefined, you shouldn't force this as an expected response, if you use it in a method that should always return a value, then it should represent an error state internally.
Use null for an intentional or non-match response.
As for how/when to check...
undefined, null, 0, an empty string, NaN and false will be FALSE via coercion. These are known as "falsy" values... everything else is true.
Your best bet is coercion then testing for valid exception values...
var something; //undefined
something = !!something; //something coerced into a boolean
//true if false, null, NaN or undefined
function isFalsish(value) {
return (!value && value !== "" && value !== 0);
}
//get number or default
function getNumber(val, defaultVal) {
defaultVal = isFalsish(defaultVal) ? 0 : defaultVal;
return (isFalsish(val) || isNaN(val)) ? defaultVal : +val;
}
Numeric testing is the real bugger, since true, false and null can be coerced into a number, and 0 coerces to false.
I would treat them as 2 completely different values, and check for the one you know might occur.
If you're checking to see if something has been given a value yet, check against undefined.
If you're checking to see if the value is 'nothing,' check against 'null'
A slightly contrived example:
Say you have a series of ajax requests, and you're morally opposed to using callbacks so you have a timeout running that checks for their completion.
Your check would look something like this:
if (result !== undefined){
//The ajax requests have completed
doOnCompleteStuff();
if (result !== null){
//There is actually data to process
doSomething(result);
}
}
tldr; They are two different values, undefined means no value has been given, null means a value has been given, but the value is 'nothing'.
I had an interesting interview question today that stumped me a little. I was asked about falsey values. So undefined, NaN, null, 0, and an empty string all evaluate to false. What is the reason this is useful to know in JavaScript? The only thing I can think of is instead of having to do this:
if (mystring === '' || mystring === undefined) { }
I can do this:
if (!mystring)
Is this the only useful application?
One dangerous issue of falsey values you have to be aware of is when checking the presence of a certain property.
Suppose you want to test for the availability of a new property; when this property can actually have a value of 0 or "", you can't simply check for its availability using
if (!someObject.someProperty)
/* incorrectly assume that someProperty is unavailable */
In this case, you must check for it being really present or not:
if (typeof someObject.someProperty == "undefined")
/* now it's really not available */
Also be aware that NaN isn't equal to anything, even not to itself (NaN != NaN).
There are two separate issues with 'falsey' values in JavaScript.
Firstly there is the official conversion scheme, which is what is returned by Boolean(x). This returns false when x is false or 0 or NaN or null or undefined or "" and true otherwise. This is the same behaviour as the
if (condition) {/*true path*/} else {/*false path*/}
that is, the false path is executed if Boolean(condition) would have returned false and the true path is executed otherwise. This behaviour is often used to check to see if a property is defined. However, doing that is not safe unless you are certain that the property would be an object or an array if it is defined. The safest way to test if a property is defined is to do
if (property != null) { /*property is defined*/}
which makes sure that the property is not null or undefined. If you only want to make sure the property is not undefined do
if (property !== undefined) { /*property is not undefined (but may be null)*/ }
(notice the extra = in !==).
Secondly, there are all the values that == false. This is everything that can be coerced to 0 (which is what false gets coerced to). This includes all the values that convert to false except NaN (which can't == false by virtue of it never == anything), null and undefined. But it also includes all objects that when converted to a string and then converted to a number are equal to 0. For example, this includes everything that when converted to a string is either the empty string "" or "0" or "-0" or "+0" or "0x00" or "000" or "0e0" or "0.0000"...., for example,
({toString: function() {return "-00.0e000";}}) == false
is true. Interestingly, this includes the empty array, and any nesting of arrays containing only a single other item that returns an empty or 0 string since arrays rendered as strings show only the contents without the surrounding brackets. That is,
[[[[0]]]] == false; // Because [[[[0]]]].toString() === "0"
[] == false;
[[[""]]] == false;
["0"] == false;
[[({toString: function() {return "0";}})]] == false;
The full algorithm for calculating == false is described here.
The reason this matters is because it can lead to subtle, difficult to find bugs if you don't understand most of these rules. Most important takeaways are probably how the if (condition) works and that using === avoids most of the other crazy stuff.
It's important to understand how this works in JS, so you're not surprised. Not necessarily just what is falsey, but what is truthy and how they compare to each other.
One example is that '0' is considered equal to 0 with ==, but it is not equal to '' - though 0 is. JavaScript comparison isn't always transitive.
So this means that just because (foo==bar && bar==fizz) is true, (foo==fizz) is not always true. To go with the above example, '0'==0, and 0=='', but '0'!='' - because you're comparing strings in the latter instance, so they are compared as strings and not coerced to numbers.
It is important to know that 0 evaluates to false to prevent doing things like:
if(str.indexOf('foo'))
It's useful to detect if a browser is has specific predefined objects:
if(!!navigator.geolocation){
// executes if the browser has geolocation support
}
if(!!document.createElement('canvas').getContext){
// executes if the browser supports <canvas>
}
Explanation: navigator.geolocation is an object or undefined. In the case it's an object !navigator.geolocation will return false, if it's undefined it'll return true. So, to check if a browser has geolocation enabled, you want to 'flip' the boolean once more, by adding another !.
They're also useful for setting default values...
function foo(bar){
alert(bar || "default");
}
I know a lot of people try to do
if (typeof(foo) === "undefined"){}
to get around falsiness, but that's got its own problems because
typeof(null) === "object"
for some reason
Recently I was running some of my code through JSLint when I came up with this error. The thing I think is funny about this error though is that it automatically assumes that all == should be ===.
Does that really make any sense? I could see a lot of instances that you would not want to compare type, and I am worried that this could actually cause problems.
The word "Expected" would imply that this should be done EVERY time.....That is what does not make sense to me.
IMO, blindly using ===, without trying to understand how type conversion works doesn't make much sense.
The primary fear about the Equals operator == is that the comparison rules depending on the types compared can make the operator non-transitive, for example, if:
A == B AND
B == C
Doesn't really guarantees that:
A == C
For example:
'0' == 0; // true
0 == ''; // true
'0' == ''; // false
The Strict Equals operator === is not really necessary when you compare values of the same type, the most common example:
if (typeof foo == "function") {
//..
}
We compare the result of the typeof operator, which is always a string, with a string literal...
Or when you know the type coercion rules, for example, check if something is null or undefinedsomething:
if (foo == null) {
// foo is null or undefined
}
// Vs. the following non-sense version:
if (foo === null || typeof foo === "undefined") {
// foo is null or undefined
}
JSLint is inherently more defensive than the Javascript syntax allows for.
From the JSLint documentation:
The == and != operators do type coercion before comparing. This is bad because it causes ' \t\r\n' == 0 to be true. This can mask type errors.
When comparing to any of the following values, use the === or !== operators (which do not do type coercion): 0 '' undefined null false true
If you only care that a value is truthy or falsy, then use the short form. Instead of
(foo != 0)
just say
(foo)
and instead of
(foo == 0)
say
(!foo)
The === and !== operators are preferred.
Keep in mind that JSLint enforces one persons idea of what good JavaScript should be. You still have to use common sense when implementing the changes it suggests.
In general, comparing type and value will make your code safer (you will not run into the unexpected behavior when type conversion doesn't do what you think it should).
Triple-equal is different to double-equal because in addition to checking whether the two sides are the same value, triple-equal also checks that they are the same data type.
So ("4" == 4) is true, whereas ("4" === 4) is false.
Triple-equal also runs slightly quicker, because JavaScript doesn't have to waste time doing any type conversions prior to giving you the answer.
JSLint is deliberately aimed at making your JavaScript code as strict as possible, with the aim of reducing obscure bugs. It highlights this sort of thing to try to get you to code in a way that forces you to respect data types.
But the good thing about JSLint is that it is just a guide. As they say on the site, it will hurt your feelings, even if you're a very good JavaScript programmer. But you shouldn't feel obliged to follow its advice. If you've read what it has to say and you understand it, but you are sure your code isn't going to break, then there's no compulsion on you to change anything.
You can even tell JSLint to ignore categories of checks if you don't want to be bombarded with warnings that you're not going to do anything about.
A quote from http://javascript.crockford.com/code.html:
=== and !== Operators.
It is almost always better to use the
=== and !== operators. The == and != operators do type coercion. In
particular, do not use == to compare
against falsy values.
JSLint is very strict, their 'webjslint.js' does not even pass their own validation.
If you want to test for falsyness. JSLint does not allow
if (foo == null)
but does allow
if (!foo)
To help explain this question and also explain why NetBeans (from) 7.3 has started showing this warning this is an extract from the response on the NetBeans bug tracker when someone reported this as a bug:
It is good practice to use === rather than == in JavaScript.
The == and != operators do type coercion before comparing. This is bad because
it causes ' \t\r\n' == 0 to be true. This can mask type errors. JSLint cannot
reliably determine if == is being used correctly, so it is best to not use ==
and != at all and to always use the more reliable === and !== operators
instead.
Reference
Well it can't really cause problems, it's just giving you advice. Take it or leave it. That said, I'm not sure how clever it is. There may well be contexts in which it doesn't present it as an issue.
You can add this to the previous line to disable these warning.
// eslint-disable-next-line