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 g
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!==
.
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
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.
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
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.