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;
}
};
}
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
}
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.
Say I have the following objects in Javascript:
var a = { xxx: 33 };
var b = { xxx: 33 };
var c;
c = a;
What is the Javascript test that will tell me whether I am dealing with the same object instance? In other words, it should return false for a and b, b and c, but true for a and c.
You just need this
if(c == a) {
// same instance
}
a == b and b == c will return false
Just a standard equality test:
( a == c ) // true
( a == b ) // false
I know the question is about checking if two objects are the same instance but this thread will not be complete without the following.
If you are after checking whether 2 objects are the same, a double equal == is enough. However, for value types (primitives), you may be in a for surprise. Check out the following:
var a = 1; // Integer 1
var b = '1' // String '1'
if (a == b) console.log('Same.');
else console.log('Not same.');
Above will print Same.. To avoid that, use the triple equal === which means two things:
Are they the same value?
Are they the same type?
Or you can use Object.is method like Object.is(a, b).
if (a === b) console.log('Same.');
else console.log('Not same.');
if (Object.is(a, b)) console.log('Same for Object.is.');
else console.log('Not same for Object.is.');
Above will print Not same. and Not same for Object.is..
Some More Info
Below is some more information which has been copy/pasted from this article:
Which operation you choose depends on what sort of comparison you are looking to perform. Briefly:
double equals (==) will perform a type conversion when comparing two things, and will handle NaN, -0, and +0 specially to conform to IEEE 754 (so NaN != NaN, and -0 == +0);
triple equals (===) will do the same comparison as double equals (including the special handling for NaN, -0, and +0) but without type conversion; if the types differ, false is returned.
Object.is does no type conversion and no special handling for NaN, -0, and +0 (giving it the same behavior as === except on those special numeric values).
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.
Conclusion
My two cents on this would be to get into the habit of always using triple equals === because it cannot hurt you but double equals == can indeed hurt you. You may use double equals == when you just care about the value and the thing you are comparing are primitives; but even this is discouraged because it mostly means a flaw in design. Languages like TypeScript will even avoid that i.e. comparing a '1' to 1 without being explicit about it.
The following are examples that make sense to me.
isFinite(5) // true - makes sense to me, it is a number and it is finite
typeof 5 // "number"
isFinite(Infinity) // false - makes sense for logical reasons
typeof Infinity // "number"
isFinite(document) // false - makes sense as well, it's not even a number
typeof document // "object"
The following is where I get confused.
isFinite(null) // true - Wait what? Other non-number objects returned false. I see no reason?
typeof null // "object"
I just don't see the reasoning behind this.
What I'd like is the most low-level answer possible.
I think null is being converted to 0, why? What other impacts does this have?
The ECMAScript spec (5.1) defines isFinite to act as such:
isFinite (number)
Returns false if the argument coerces to NaN, +∞, or −∞, and otherwise returns true.
If ToNumber(number) is NaN, +∞, or −∞, return false.
Otherwise, return true.
In other words, isFinite is calling ToNumber on whatever's passed in, and then comparing it to either pos/neg infinity or NaN.
In JavaScript (note the use of != instead of the more common !==, causing the type cast):
function isFinite(someInput) {
return !isNaN(someInput) &&
someInput != Number.POSITIVE_INFINITY &&
someInput != Number.NEGATIVE_INFINITY;
}
(As noted in the comments below, someInput != NaN is not needed, as NaN is defined to not be equivalent to everything, including itself.)
Now, why is null converted to zero (as opposed to undefined)? As TylerH says in the comments, null means that a value exists, but is empty. The mathematical representation of this is 0. undefined means that there isn't a value there, so we get NaN when trying to call ToNumber on it.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.5
However, ECMAScript 6 is bringing along a non-converting isFinite as a property of Number. Douglas Crockford suggested it here: http://wiki.ecmascript.org/doku.php?id=harmony:number.isfinite
From MDN:
The global isFinite() function determines whether the passed value is
a finite number. If needed, the parameter is first converted to a
number.
So, it's converted to a number...
isFinite(null)
isFinite(+null) //convert to a number
isFinite(0) // true because +null or Number(null) = 0
The spec says that the global isFinite() method will forcibly convert the parameter to a number.
You could, however, use (at your own risk) the EcmaScript 6 spec's Number.isFinite() which doesn't perform this conversion.
Number.isFinite(null) // false
Or, like lodash and underscore do it...
var _.isFinite = function(obj) {
return isFinite(obj) && !isNaN(parseFloat(obj));
};
isFinite calls ToNumber on its argument. So
> Number(null)
0
> Number(document)
NaN
> isFinite(0)
true
> isFinite(NaN)
false
> isFinite(null)
true
> isFinite(document)
false
Because, if you say
Number(null) === 0 which is finite
See To Number Conversions
Which says that, for argument type null result is +0
isFinite typecasts it's argument to a number, if it's not already a number. Essentially you have isFinite(Number(null)) and Number(null) === 0. Which is finite.
Beside null, you find these examples interesting too:
alert(isFinite(' ')); //true
alert(isFinite('')); //true
alert(isFinite(null)); //true
alert(isFinite(!undefined)); //true
In JavaScript implicit conversion take place, This conversion try to convert bool to integer when comparing numbers with boolean, or number to string when comparing string with numbers. If you treat any data-type as number it implicitly converted to number so all above cases return zero which is finite. See Here
If you try Number(undefined) it give you a NaN on negate this would produce a 1 which is finite.
Below is a pure function f for which f(a) !== f(b) despite a === b (notice the strict equalities) for some values of a and b:
var f = function (x) {
return 1 / x;
}
+0 === -0 // true
f(+0) === f(-0) // false
The existence of such functions can lead to difficult-to-find bugs. Are there other examples I should be weary of?
Yes, because NaN !== NaN.
var f = function (x) { return Infinity - x; }
Infinity === Infinity // true
f(Infinity) === f(Infinity) // false
f(Infinity) // NaN
Some other examples that yield NaN whose arguments can be strictly equal:
0/0
Infinity/Infinity
Infinity*0
Math.sqrt(-1)
Math.log(-1)
Math.asin(-2)
this behaviour is perfectly ok, because, in mathematical theory, -0 === +0 is true, and 1/(-0) === 1/(+0) is not, because -inf != +inf
EDIT: although I am really surprised that javascript can in fact handle these kinds of mathematical concepts.
EDIT2: additionally, the phenomenon you described is completely based on the fact, that you divide by zero from which you should expect at least some strange behaviour.
1/+0 is Infinity and 1/-0 -Infinity, while +0 === -0.
This can be explained by the fact that ECMA defines -0 to equal +0 as a special case, while in other operations these two values retain their different properties, which result in some inconsistencies.
This is only possible because the language explicitly defines two non-equal values to be equal, that in fact are not.
Other examples, if any, should be based on the same sort of artificial equality, and given http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.6 there is no other such excention, so probably no other example of this.
If it's of any use, we can ensure that 0 is not -0 by adding 0 to it:
var f = function(x) {
return 1 / (x + 0);
}
f(+0) === f(-0)
In ECMAScript 3, another example where === behaves surprisingly is with joined functions. Consider a case like this:
function createConstantFunction(result) {
return function () {
return result;
};
}
var oneReturner = createConstantFunction(1); // a function that always returns 1
var twoReturner = createConstantFunction(2); // a function that always returns 2
An implementation is allowed to "join" the two functions (see §13.2 of the spec), and if it does so, then oneReturner === twoReturner will be true (see §13.1.2), even though the two functions do different things. Similarly with these:
// a perfect forwarder: returns a sort of "duplicate" of its argument
function duplicateFunction(f) {
return function (f) {
return f.apply(this, arguments);
};
}
var myAlert = duplicateFunction(alert);
console.myLog = duplicateFunction(console.log);
Here an implementation can say that myAlert === console.myLog, even though myAlert is actually equivalent to alert and console.myLog is actually equivalent to console.log.
(However, this aspect of ECMAScript 3 was not preserved in ECMAScript 5: functions are no longer allowed to be joined.)
I'm not so sure this is so scary ;-) Javascript is not a pure language and the presence of +/-0 and the equality of -0 and +0 are specific to IEEE-754 and are "well defined", even if perhaps sometimes surprising. (Even NaN != NaN always being true is well defined, for instance.)
From signed zero:
According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators...
Technically, because the two inputs to f are different, then the result can also be different. For what it's worth, Haskell will treat 0 == -0 as true but will treat (1 / 0) == (1 / (-0)) as false.
However, I do find this an interesting question.
Happy coding.
There are many such functions, here is another example
function f (a) {
return a + 1;
}
1 == "1"
but f(1) != f("1")
This is because equality is a nuanced concept.
Perhaps more scary is that in your example -0 === +0.