What is the difference between (NaN != NaN) and (NaN !== NaN)?

亡梦爱人 提交于 2019-11-28 15:36:27

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:

  1. ReturnIfAbrupt(x).
  2. ReturnIfAbrupt(y).
  3. If Type(x) is the same as Type(y), then

    Return the result of performing Strict Equality Comparison x === y.

  4. ...

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.

jkdev

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

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.

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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!