首页 文章

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

提问于
浏览
146

首先,我想提一下,我知道如何 isNaN()Number.isNaN() 工作 . 我正在阅读David Flanagan的The Definite Guide,他给出了一个如何检查值是否为 NaN 的示例:

x !== x

当且仅当 xNaN 时,这将导致 true .

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

x != x

表现方式相同 . 使用这两个版本是否安全,或者我在JavaScript中遗漏了一些值,这些值将返回 x !== xx !== xfalsex != x

5 回答

  • 22

    首先,我要指出 NaN 是一个非常特殊的值:根据定义,它必须在IEEE-754中,它允许多个不同的"not a number"值 . )这就是为什么会出现这种情况; JavaScript中的所有其他值都等于它们自己, NaN 只是特殊的 .

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

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

    Abstract Equality Operation定义的开头就可以看出这一点:

    ReturnIfAbrupt(x) . ReturnIfAbrupt(Y) . 如果Type(x)与Type(y)相同,则返回执行Strict Equality Comparison x === y的结果 . ...

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

    因此,如果Flanagan是正确的,只有 NaN 将为 x !== x 赋予真,那么我们可以确定只有 NaN 才会为 x != x 赋予真 .

    许多JavaScript程序员默认使用 ===!== 来避免松散运算符所做的类型强制的一些陷阱,但是在这种情况下使用了严格与松散运算符 .

  • 2

    出于NaN的目的, !=!== 做同样的事情 .

    但是,许多程序员在JavaScript中避免使用 ==!= . 例如,道格拉斯·克罗克福德认为它们属于JavaScript语言的“bad parts”,因为它们表现出意想不到的混乱方式:

    JavaScript有两组相等运算符:===和!==,它们的邪恶双胞胎==和!= . 好的工作方式与您期望的方式相同 . ......我的建议是永远不要使用邪恶的双胞胎 . 相反,始终使用===和!== .

  • 125

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

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

    然后我们有

    x != x // false
    

    x !== x // true
    
  • 0

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

    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等)都表现出这种确切的行为,人们对它很好 .

  • 37

    有时,图像比单词更好,检查这个table(这是我做出这个答案而不是评论的原因,因为它获得了更好的可见性) .

    在那里你可以看到严格的相等比较(===)只有在类型和内容匹配时才返回true,所以

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

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

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

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

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

相关问题