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
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.
In javascript, which will be better way to check conditional statement in terms of performance, robustness and which is the best practice?
var x = null;
// this condition is checked frequently and x will be set to null or some value accordingly
if(x !== null){...}
OR
if(!!x){...}
You could just do
if (x) { ... }
Simply says, if x is a truthy value.
As Nina pointed out. I would always add some extra validation, depending on what I'm expecting.
if (x && x > 0) { ... }
Or
if (x && x instanceof Array)
But I'm always checking x has some sort of value and isn't undefined or null
It's never necessary to write if(!!x){...}. That is exactly the same thing as writing if(x){...}. Using the ! operator twice converts a value to a boolean that reflects whether it is "truthy" or not. But the if statement does that anyway: it tests whether the value you provide is "truthy". So whether you use !! or not it will do the same thing.
if(x !== null){...} is something else entirely. It doesn't just check whether x is "truthy", it specifically compares the value of x with null. For example, if x has the numeric value 0, if(x){...} or if(!!x){...} will not execute the ... code, because 0 is a "falsy" value, but if(x!==null) will execute the ... code, because 0 is not the same value as null.
A related example is if(x!=null){...} or if(x==null){...}. (Note the use of != or == instead of !== or ===.) This is a bit of a special case in JavaScript. When you compare against null using the != or == operator, it actually compares against either null or undefined and treats those two values the same. In other words, if x is either null or undefined, then if(x==null){...} will execute the ... code, but if(x!=null){...} will not execute the ... code.
It's generally recommended to avoid the == and != operators and use the strict comparison === or !== instead, but treating null and undefined the same can be useful in some situations, so this is a case where the non-strict operators are helpful.
In any case, the real question to ask is what is the purpose of your code, and what specifically do you need to test for here?
Assuming you need to check for a value which is strict inequality !== to null
this condition is checked frequently and x will be set to null or some value accordingly
if (x !== null) { /* */ }
Then you can only use the above comparison. Any other comparison would return a wrong result.
For example
var x = 0;
if (x !== null) { // true
console.log(x + ' !== null');
}
if (x) { // false
console.log(x);
}
// some more checks
console.log(undefined !== null); // true
console.log(undefined != null); // false
Edit: My response was quite wrong which I learned after my conversation with Nina Scholz in her own response to this thread. I updated accordingly.
There are many ways to check values depending on the type you expect to use. Therefore the problem is not so much about performance as it is with correct evaluation. Starting with your examples:
if(x != null)
This will evaluate to false if the value of x is either null or `undefined'.
The next case:
if(!!x)
This is an entirely different operation. It casts the value of x as a boolean, and in most cases if(x) will work the same way. But now, if the value is falsy, like 0, the empty string, the expression returns false. So, if expecting a number, you should check for the zero value:
if(x || (0 === x))
Bear in mind that if x were anything other than an int, the expression returns true.
And the case where you expect a string:
if(x || ('' === x))
Same thing here, if x was, say 12, the expression returns true.
I could go on with lots of examples. Unfortunately there are certain expressions that work in unexpected ways. For instance, it should be easy to check if a value is a number by calling isNaN(number), but if the value is an empty string or a representation of an array index ('2'), isNaN returns false.
I recommend you to check this table with all the type conversions so that you become more aware on how to check the validity of a value.
When I compare undefined and null against Boolean false, the statement returns false:
undefined == false;
null == false;
It return false. Why?
With the original answer pointing to the spec being deleted, I'd like to provide a link and short excerpt from the spec here.
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
The ECMA spec doc lists the reason that undefined == false returns false. Although it does not directly say why this is so, the most important part in answering this question lies in this sentence:
The comparison x == y, where x and y are values, produces true or false.
If we look up the definition for null, we find something like this:
NULL or nil means "no value" or "not applicable".
In Javascript, undefined is treated the same way. It is without any value. However, false does have a value. It is telling us that something is not so. Whereas undefined and null are not supposed to be giving any value to us. Likewise, there is nothing it can convert to for its abstract equality comparison therefore the result would always be false. It is also why null == undefined returns true (They are both without any value). It should be noted though that null === undefined returns false because of their different types. (Use typeof(null) and typeof(undefined) in a console to check it out)
What I'm curious of though, is that comparing NaN with anything at all will always return false. Even when comparing it to itself. [NaN == NaN returns false]
Also, another odd piece of information: [typeof NaN returns "number"]
Strict Equality
If possible, you should avoid using the == operator to compare two values. Instead use === to truly see if two values are equal to each other. == gives the illusion that two values really are exactly equal when they may not be by using coercion. Examples:
5 == "5" is true
5 === "5" is false
"" == false is true
"" === false is false
0 == false is true
0 === false is false
From the incomparable MDN, sponsored by the company of JavaScript's creator.
JavaScript provides three different value-comparison operations:
strict equality (or "triple equals" or "identity") using ===,
loose equality ("double equals") using ==,
and Object.is (new in ECMAScript > 6).
The choice of which operation to use depends on what sort of
comparison you are looking to perform.
Briefly, double equals will perform a type conversion when comparing
two things; triple equals
will do the same comparison without type conversion (by simply always
returning false if the types differ); and Object.is will behave the
same way as triple equals, but with special handling for NaN and -0
and +0 so that the last two are not said to be the same, while
Object.is(NaN, NaN) will be true. (Comparing NaN with NaN
ordinarily—i.e., using either double equals or triple equals—evaluates
to false, because IEEE 754 says so.) Do note that the distinction
between these all have to do with their handling of primitives; none
of them compares whether the parameters are conceptually similar in
structure. For any non-primitive objects x and y which have the same
structure but are distinct objects themselves, all of the above forms
will evaluate to false.
For a visual overview of the whole picture of equality in JavaScript:
https://dorey.github.io/JavaScript-Equality-Table/
The truth is, this seemingly "bad" aspect of JavaScript is a source of power when you understand how it works.
So undefined really means undefined. Not False, not True, not 0, not empty string. So when you compare undefined to anything, the result is always false, it is not equal to that.
You question is half, as we compare undefined/ null to any other types.
we will have false return.
There is no coercion happening, even we are using == operator.
This is so because it is so. :)
Read the ECMA standards here: https://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
Undefined is not the same thing as false, false is a boolean object (which has a value of 0 therefore it is indeed defined).
An example:
var my_var;
var defined = (my_var === undefined)
alert(defined); //prints true. It is true that my_var is undefined
my_var = 22;
defined = (my_var === undefined)
alert(defined); //prints false. my_var is now defined
defined = (false === undefined)
alert(defined); //prints false, false is defined
defined = (true === undefined)
alert(defined); //prints false, true is defined
According to the specification flow:
If Type(y) is Boolean, return the result of the comparison x ==
ToNumber(y).
1) undefined == false; -> undefined == Number(false); -> undefined == 0;
2) null == false; -> null == Number(false); -> null == 0;
There is no rule for these cases, so go with the behavior in the last step:
Return false.
[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'.
What is the value of document.write(false == null). It should be true right (converted to same type before comparing - null is converted to false), if null is false then comparision should return true, but printing false. Why?
Your initial assumption is incorrect (as you may have worked out by the output!). == does indeed do type coercion, but there result is not necessarily what you expect. null is an object, whose type is null - false is an object whose type is boolean. There is no coercion under which objects of the null and boolean types can be equal, which is why this is false.
undefined objects, on the other hand, can be coerced to null.
Note that the double-equals operator behaves in a bizarre way due to this - it's not even transitive. I would strongly suggest against its use unless somehow you know exactly how it will behave under your domain of inputs and you're sure you want this. It will almost certainly be better to coerce manually and use the === operator instead.
Edit: my original answer was completely incorrect....the below IS correct
(false == null) === false
(!null) === true
The 4th or 5th most popular answer in this post: Strangest language feature has a javascript truth comparison table.