(NaN!= NaN)和(NaN!== NaN)有什么区别?
首先我想提一下,我知道isNaN()
和Number.isNaN()
是如何工作的。 我正在阅读David Flanagan的“ The Definite Guide” ,他给出了一个如何检查值是否为NaN
的例子:
x !== x
当且仅当x
是NaN
这将导致true
。
但是现在我有一个问题:他为什么要严格比较呢? 因为它似乎
x != x
performance方式相同。 是否安全地使用两个版本,或者我缺less一些在JavaScript中的值,将返回为x !== x
和为x != x
false
?
首先让我指出, NaN
是一个非常特殊的价值:根据定义,它不等于自身。 这来自JavaScript数字所依据的IEEE-754标准。 即使这些位是完全匹配的,“非数字”值也不会等于自身。 (它们不一定在IEEE-754中,它允许多个不同的“不是一个数字”的值。)这就是为什么这甚至出现; JavaScript中的所有其他值都等于他们自己, NaN
只是特殊的。
…我错过了JavaScript中的一些值,将返回为x!== x和真正的x!= x?
不你不是。 !==
和!=
之间的唯一区别是后者会根据需要进行types强制,以使操作数的types相同。 在x != x
,操作数的types是相同的,所以它和x !== x
完全一样。
从“ 抽象平等操作 ”的定义开始就很清楚:
- ReturnIfAbrupt(X)。
- ReturnIfAbrupt(Y)。
如果types(x)与types(y)相同,则
返回执行严格平等比较x === y的结果。
…
前两个步骤是基本的pipe道。 所以实际上, ==
第一步是查看types是否相同,如果是,则执行===
。 !=
和!==
只是否定版本。
所以如果弗拉纳根是正确的,只有NaN
才会对x !== x
给出正确的结论,我们可以肯定的是,只有NaN
才会给x != x
赋予正确性。
许多JavaScript程序员默认使用===
和!==
来避免松散运算符types强制的一些缺陷,但在这种情况下,没有什么可以读到Flanagan使用严格运算符和松散运算符的。
为了NaN的目的, !=
和!==
做同样的事情。
但是,许多程序员在JavaScript中避免使用==
或!=
。 例如,道格拉斯·克罗克福德(Douglas Crockford)认为他们是JavaScript语言的“ 坏部分 ”之一,因为他们的行为是出乎意料和混乱的:
JavaScript有两套相等运算符:
===
和!==
,以及他们的双胞胎==
和!=
。 好的那些以你期望的方式工作。…我的build议是永远不要使用邪恶的双胞胎。 相反,总是使用
===
和!==
。
只是为了好玩,让我给你展示一个人为的例子,其中x
不是NaN
但是操作符的行为却是不同的。 首先定义:
Object.defineProperty( self, 'x', { get: function() { return self.y = self.y ? 0 : '0'; } } );
那我们有
x != x // false
但
x !== x // true
我只想指出, 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
正如其他答案指出的那样, ==
执行types转换,但是和其他语言一样,NaN表示计算失败,出于好的理由不等于自己。
出于某种原因,人们用JS来解决这个问题,但是大多数具有双精度的语言(即C,Java,C ++,C#,Python和其他)都performance出这种确切的行为,人们对它很好。
有时候,图像比单词好,查看这个表 (这是我做这个答案的原因,而不是一个评论是因为它获得更好的可见性)。
在那里你可以看到,严格的相等比较(===)只有在types和内容匹配时才会返回true,所以
var f = "-1" === -1; //false
虽然抽象的相等比较(==)只通过转换types,然后严格比较它们来检查内容*:
var t = "-1" == -1; //true
虽然目前尚不清楚,但没有咨询ECMA ,JavaScript在比较时会考虑什么,以下面的代码评估为真。
var howAmISupposedToKnowThat = [] == false; //true