(NaN!= NaN)和(NaN!== NaN)之间有什么区别?

时间:2015-12-14 07:44:14

标签: javascript nan

首先,我想提一下,我知道isNaN()Number.isNaN()是如何运作的。我正在阅读David Flanagan撰写的 The Definite Guide ,他举例说明了如何检查该值是否为NaN

x !== x

当且仅当truex时,这将产生NaN

但现在我有一个问题:他为什么要使用严格的比较?因为它似乎

x != x

表现方式相同。使用这两个版本是否安全,或者我在JavaScript中遗漏了一些价值,这些价值会为true返回x !== xfalse会返回x != x

5 个答案:

答案 0 :(得分:126)

首先,我要指出NaN是一个非常特殊的值:根据定义,它不等于它自己。这来自JavaScript数字所依据的IEEE-754标准。 "不是数字"即使这些位完全匹配,值也永远不会等于它自身。 (它们不一定在IEEE-754中,它允许多个不同的"而不是数字"值。)这就是为什么会出现这种情况; JavaScript中的所有其他值都等于它们自己,NaN只是特殊的。

  

...我错过了JavaScript中的一些值,它会为x!== x返回true而false为x!= x?

不,你不是。 !==!=之间的唯一区别是,如果需要,后者将执行类型强制以使操作数的类型相同。在x != x中,操作数的类型是相同的,因此它与x !== x完全相同。

Abstract Equality Operation

的定义开始就清楚了
  
      
  1. ReturnIfAbrupt(X)。
  2.   
  3. ReturnIfAbrupt(Y)。
  4.   
  5. 如果Type(x)与Type(y)相同,那么

         

    返回执行Strict Equality Comparison x === y。

  6. 的结果   
  7. ...

  8.   

前两个步骤是基本管道。实际上,==的第一步是查看类型是否相同,如果是,则执行===!=!==只是其中的否定版本。

因此,如果Flanagan是正确的,只有NaN才会为x !== x提供真实,我们可以肯定只有NaN才能为x != x提供真实1}}。

许多JavaScript程序员默认使用===!==来避免松散运算符所造成的类型强制的一些陷阱,但没有什么可以读到Flanagan的使用在这种情况下,严格与松散的运算符。

答案 1 :(得分:37)

出于NaN的目的,!=!==执行相同的操作。

但是,许多程序员在JavaScript中避免使用==!=。例如,道格拉斯·克罗克福德认为他们是" bad parts" JavaScript语言,因为它们以令人意想不到和令人困惑的方式运行:

  

JavaScript有两组相等运算符:===!==,以及它们的邪恶双胞胎==!=。优秀的工作方式与您期望的方式相同。

     

......我的建议是永远不要使用邪恶的双胞胎。相反,请始终使用===!==

答案 2 :(得分:22)

为了好玩,让我向您展示一个人工示例x不是NaN,但操作员的行为却无论如何。首先定义:

Object.defineProperty(
  self,
  'x',
  { get: function() { return self.y = self.y ? 0 : '0'; } }
);

然后我们

x != x // false

x !== x // true

答案 3 :(得分:2)

我只想指出NaN不是唯一在不使用全局对象的情况下产生x !== x的东西。有很多聪明的方法可以触发这种行为。这是一个使用getters:

var i = 0, obj = { get x() { return i++; }};
with(obj) // force dynamic context, this is evil. 
console.log(x === x); // false

正如其他答案所指出的,==执行类型coersion,但与其他语言和标准相同 - NaN表示计算失败,并且有充分理由不等于它自己。

出于某些原因,除了我之外,人们在JS中遇到了这个问题,但是大多数具有双倍语言的语言(即C,Java,C ++,C#,Python等)都表现出这种确切的行为,而且人们也很好。

答案 4 :(得分:0)

有时候,图片比单词更好,请查看table(这是我将其作为答案的原因而不是评论,因为它可以获得更好的可见性)。

在那里你可以看到,如果类型和内容匹配,则严格相等比较(===)仅返回true,所以

var f = "-1" === -1; //false

虽然抽象相等比较(==)仅通过转换类型检查内容*,然后严格比较它们:

var t = "-1" == -1; //true

虽然目前还不清楚,但没有咨询ECMA,JavaScript在比较时会考虑什么,以及代码如下评估为真的方式。

 var howAmISupposedToKnowThat = [] == false; //true