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.
Related
When I want to make sure a variable x is defined, before using it, I use:
if (typeof x !== "undefined") {
// do stuff with x
}
but I've noticed that others, e.g. in this question, use !== instead of != for the comparison. Which one should I be using, and why?
Note: I realize I can be using !==. The question is whether I should (and whether there will be any difference in behavior).
As noted in a comment by VLAZ, the typeof operator is guaranteed to return a string. If you compare the result to another string, then == and === (or != and !==) will do the exact same thing.
actually, the best approach would be to check if a value is falsy, and based on MDN this is the list of falsy values:
false The keyword false
0 The number zero
0n BigInt, when used as a boolean, follows the same rule as a Number. 0n is falsy.
"", '', ``
This is an empty string (the length of the string is zero). Strings in JavaScript can be defined with double quotes "", single quotes '', or Template literals ``.
null null - the absence of any value
undefined undefined - the primitive value
NaN NaN - not a number
so based on your code what you can do is simply:
if (!x) { // check for all the falsy values.
// do stuff with x
}
in the other hand, you ask for the difference of != and !==, well basically taking some examples you can see the difference:
0 == false // true, because false is equivalent of 0
0 === false // false, because both operands are of different type
2 == "2" // true, auto type coercion, string converted into number
2 === "2" // false, since both operands are not of same type
as mentioned by #VLAZ comment, these cases will only work if the variable x is defined, otherwise you will have the following error:
"Uncaught ReferenceError: x is not defined"
so on your case you could only use != because you will compare string vs string and you will avoid having to check if the variable was or not created.
if (typeof x != "undefined") {
// do stuff with x
}
I have an object that contains a string HelloWorld in the attribute hello. I want to check for two strings, and if it does not match with either one, then I want to execute certain code.
var item = { hello: "HelloWorld" }
item.hello !== "HelloWorld" && item.hello !== "GoodbyeWorld" // false, correct
However, I feel this can be optimized and made more readable:
item.hello !== ("GoodbyeWorld" && "HelloWorld") // false, correct
item.hello !== ("HelloWorld" && "GoodbyeWorld") // true WTF?
I expected both checks to be falsy, but surely I'm missing something here. I think I do not have a correct understanding of the AND/OR operator in javascript, or I am using the parenthesis in a wrong manner. Can anyone explain?
JSFiddle example
The result of "HelloWorld" && "GoodbyeWorld" is "GoodbyeWorld" which is why you're getting the result you are, the previous way you were doing it is the simplest solution
Let's take a look at this line
item.hello !== ("HelloWorld" && "GoodbyeWorld") // true WTF?
The logical AND operator evaluates its right operand, if lVal is a truthy value.
Note, a truthy value is every value which is not falsy (null,false,0,"",undefined,NaN)
Since "HelloWorld" is indeed truthy
The expression ("HelloWorld" && "GoodbyeWorld") evaluates to "GoodbyeWorld" and you're effectively comparing
item.hello !== "GoodbyeWorld" which can be reduced to "HelloWorld" !== "GoodbyWorld"
Hence, is true
However, if you're on an ES5 compatible environment you could use Array.prototype.indexOf to simplify it.
!~["HelloWorld","GoodbyWorld"].indexOf(item.hello) //false
the above returns true if item.hello is not contained in the array
No, you can't optimise the expression that way. What you are doing is elliminating one of the strings, so that you are only doing one of the comparisons.
The && operator uses short circuit evaluation, which means that if the first operand is truthy, it will just return the second operand.
So, what your code is doing is to compare the hello property value to the second one of the strings, which explains the results that you get.
item.hello !== "HelloWorld" && item.hello !== "GoodbyeWorld"
is the proper way to test whether item.hello is distinct from "HelloWorld" and "GoodbyeWorld".
An expression A && B in JavaScript yields a result which is either A or B and it's that result, that is compared to your item.hello.
In Javascript:
NaN === NaN; // false
I was trying to determine when isNaN(foo) is not just equivalent to +foo "is" NaN. But I don't know how to tell if something is NaN except by using isNaN, which says yes for many things, none of which === NaN.
So I think the right way to do this would be to work around other possibilities:
typeof NaN === 'number' // true
Therefore I think
typeof(foo) === 'number' && isNaN(foo)
Is the closest to what I am thinking of. It makes sense since it makes sense that NaN would be the only number that isn't a number, or something. Is this correct, and is this the best way?
Use that to your advantage:
foo !== foo
This is equivalent to typeof foo === 'number' && isNaN(foo), and is what Underscore.js uses to check for exactly NaN, too.
The reason that NaN isn't equal to itself is that two calculations can become NaN for different reasons. If you do two calculations and compare the results, you don't want them to be equal if one of the values are NaN, or both of them.
The isNaN method works fine as long as you only use it on numerical values. It gives unintuitive results for a lot of other types, so you simply shouldn't use it on anything other than numbers.
If you can use ECMAScript 6, you have Object.is:
return Object.is(foo, NaN);
Object.is() determines whether two values are the same value. Two values are the same if one of the following holds:
[...]
both NaN
MDN also suggests a Polyfill if Object.is isn't defined (uses the same foo!==foo trick):
if (!Object.is) {
Object.is = function(x, y) {
// SameValue algorithm
if (x === y) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
};
}
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
Throughout many third-party libraries and best practices blogs/recommendations, etc... it is common to see syntax like this:
typeof x === 'object' (instead of typeof x == 'object')
typeof y === 'string' (instead of typeof x == 'string')
typeof z === 'function' (instead of typeof x == 'function')
If the typeof operator already returns a string, what's the need to type check the return value as well? If typeof(typeof(x)) is always string, no matter what x actually is, then == should be sufficient and === unnecessary.
Under what circumstances will typeof not return a string literal? And even if there's some fringe case why is the additional type check being used for object, string, function, etc...
To answer the main question - there is no danger in using typeof with ==. Below is the reason why you may want to use === anyway.
The recommendation from Crockford is that it's safer to use === in many circumstances, and that if you're going to use it in some circumstances it's better to be consistent and use it for everything.
The thinking is that you can either think about whether to use == or === every time you check for equality, or you can just get into the habit of always writing ===.
There's hardly ever a reason for using == over === - if you're comparing to true or false and you want coercion (for example you want 0 or '' to evaluate to false) then just use if(! empty_str) rather than if(empty_str == false).
To those who don't understand the problems of == outside of the context of typeof, see this, from The Good Parts:
'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
If the typeof operator already returns
a string, what's the need to type
check the return value as well? If
typeof(typeof(x)) is always string, no
matter what x actually is, then ==
should be sufficient and ===
unnecessary.
It's subjective. You can just as easily turn this around, and ask, "Why would you use == when you don't expect implicit conversions?" Both work fine here, so use the one you feel expresses your intention better. Try to be consistent within a project.
There's no reason at all to favour === over == in this case, since both operands are guaranteed to be strings and both operators will therefore give the same result. Since == is one character fewer I would favour that.
Crockford's advice on this is to use === all the time, which is reasonable advice for a beginner but pointlessly paranoid if you know the issues (covered in other answers).
Because === is quicker than ==, due to omitting type coercion.
Sure it is probably a negligible difference but it is still there.
Triple equal operators are mostly used for variable type and value checking (all in 1 expression), also known as equality without type coercion.
Example:
var a = 1;
var b = 1;
var c = "1";
var d = "1";
alert (a === b); //True, same value and same type (numeric)
alert(c === d); //True, same value and same type (string)
alert(b === c); //False, different type but same value of 1
See Doug Crockford's YUI Theater on type coercion.
If the typeof operator already returns
a string, what's the need to type
check the return value as well? If
typeof(typeof(x)) is always string, no
matter what x actually is, then ==
should be sufficient and ===
unnecessary.
The most efficient reason for not using typeof and rather the === operator would be for type coercion (interpretation) between browsers. Some browsers can pass 6=="6" as true and some wouldn't (depending on the strictness of the JS interpreter) so by introducing type coercion would clarify this.
Also, it would bring the "Object-Orientativity" approach to it since JavasScript's variables are not type-based variables (i.e. variable types are not declared on compile time like in Java).
E.g. in Java, this would fail:
if ("6" instanceof Number) { // false
Hope I answered your question.