Reputation: 35780
First of all I want to mention that I know how isNaN()
and Number.isNaN()
work. I am reading The Definite Guide by David Flanagan and he gives an example for how to check if the value is NaN
:
x !== x
This will result in true
if and only if x
is NaN
.
But now I have a question: why does he use strict comparison? Because it seems that
x != x
behaves the same way. Is it safe to use both versions, or I am missing some value(s) in JavaScript that will return true
for x !== x
and false
for x != x
?
Upvotes: 152
Views: 15814
Reputation: 1074038
First, let me point out that NaN
is a very special value: By definition, it's not equal to itself. That comes from the IEEE-754 standard that JavaScript numbers draw on. The "not a number" value is never equal to itself, even when the bits are an exact match. (Which they aren't necessarily in IEEE-754, it allows for multiple different "not a number" values.) Which is why this even comes up; all other values in JavaScript are equal to themselves, NaN
is just special.
...am I missing some value in JavaScript that will return true for x !== x and false for x != x?
No, you're not. The only difference between !==
and !=
is that the latter will do type coercion if necessary to get the types of the operands to be the same. In x != x
, the types of the operands are the same, and so it's exactly the same as x !== x
.
This is clear from the beginning of the definition of the Abstract Equality Operation:
- ReturnIfAbrupt(x).
- ReturnIfAbrupt(y).
If Type(x) is the same as Type(y), then
Return the result of performing Strict Equality Comparison x === y.
...
The first two steps are basic plumbing. So in effect, the very first step of ==
is to see if the types are the same and, if so, to do ===
instead. !=
and !==
are just negated versions of that.
So if Flanagan is correct that only NaN
will give true for x !== x
, we can be sure that it's also true that only NaN
will give true for x != x
.
Many JavaScript programmers default to using ===
and !==
to avoid some pitfalls around the type coercion the loose operators do, but there's nothing to read into Flanagan's use of the strict vs. loose operator in this case.
Upvotes: 130
Reputation: 370
As sometimes, images are better than words, check this table (which is the reason for me to make this an answer instead a comment is because it gets better visibility).
There you can see that strict equality comparison (===) only returns true if type and content match, so
var f = "-1" === -1; //false
While abstract equality comparison (==) checks only the content* by converting types and then strictly comparing them:
var t = "-1" == -1; //true
Though it's not clear, without consulting ECMA, what JavaScript considers when comparing, in a way that the code bellow evaluates to true.
var howAmISupposedToKnowThat = [] == false; //true
Upvotes: 0
Reputation: 11718
For purposes of NaN, !=
and !==
do the same thing.
However, many programmers avoid ==
or !=
in JavaScript. For example, Douglas Crockford considers them among the "bad parts" of the JavaScript language because they behave in unexpected and confusing ways:
JavaScript has two sets of equality operators:
===
and!==
, and their evil twins==
and!=
. The good ones work the way you would expect....My advice is to never use the evil twins. Instead, always use
===
and!==
.
Upvotes: 38
Reputation: 276286
I just want to point out NaN
is not the only thing that produces x !== x
without using the global object. There are lots of clever ways to trigger this behavior. Here is one using getters:
var i = 0, obj = { get x() { return i++; }};
with(obj) // force dynamic context, this is evil.
console.log(x === x); // false
As other answers point out, ==
performs type coersion, but in as in other languages and par the standard - NaN indicates a computation failure, and for good reasons is not equal to itself.
For some reason beyond me people ocnsider this a problem with JS but most languages that have doubles (namely, C, Java, C++, C#, Python and others) exhibit this exact behavior and people are just fine with it.
Upvotes: 2
Reputation: 47644
Just for fun, let me show you an artificial example where x
is not NaN
but the operators behave differently anyway. First define:
Object.defineProperty(
self,
'x',
{ get: function() { return self.y = self.y ? 0 : '0'; } }
);
Then we have
x != x // false
but
x !== x // true
Upvotes: 22