(NaN!=NaN)和(NaN)之间有什么区别
What is the difference between (NaN != NaN) and (NaN !== NaN)?
首先我想说的是,我知道isNaN()
和Number.isNaN()
是如何工作的。我正在阅读David Flanagan的《确定性指南》,他给出了一个如何检查值是否为NaN
:的例子
x !== x
这将导致true
,当且仅当x
是NaN
。
但现在我有一个问题:他为什么要严格比较?因为
x != x
行为方式相同。使用这两个版本是否安全,或者我在JavaScript中缺少一些值,这些值将为x !== x
返回true
,为x != x
返回false
?
首先,让我指出NaN
是一个非常特殊的值:根据定义,它不等于自己。这源于JavaScript数字所采用的IEEE-754标准。"非数字"值永远不会等于它自己,即使比特完全匹配。(在IEEE-754中,它们不一定是这样,它允许多个不同的"非数字"值。)这就是为什么会出现这种情况;JavaScript中的所有其他值都等于它们自己,NaN
只是特殊的。
我是否在JavaScript中丢失了一些值,该值将在x中返回true!==x为false!=x?
不,你不是。!==
和!=
之间的唯一区别是,如果需要,后者将执行类型强制,以使操作数的类型相同。在x != x
中,操作数的类型是相同的,因此它与x !== x
完全相同。
这一点从抽象等式运算的定义开始就很清楚:
- ReturnIfAbrupt(x)
- ReturnIfAbrupt(y)
如果类型(x)与类型(y)相同,则
返回执行严格相等比较的结果x==y。
。。。
前两个步骤是基本的管道。因此,实际上,==
的第一步是查看类型是否相同,如果是,则执行===
。CCD_ 19和CCD_。
因此,如果Flanagan是正确的,只有NaN
对x !== x
为真,那么我们可以确信,也只有NaN
对x != x
为真。
许多JavaScript程序员默认使用===
和!==
来避免松散运算符所做的类型强制方面的一些陷阱,但在这种情况下,Flanagan使用严格与松散运算符没有什么可解读的。
对于NaN,!=
和!==
做相同的事情。
然而,许多程序员在JavaScript中避免使用==
或!=
。例如,Douglas Crockford认为它们属于";坏零件";因为它们的行为方式出乎意料且令人困惑:
JavaScript有两组相等运算符:
===
和!==
,以及它们的邪恶双胞胎==
和!=
。好的工作方式你会期望。我的建议是永远不要使用邪恶的双胞胎。请始终使用
===
和!==
。
为了好玩,让我向您展示一个人工示例,其中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
正如其他答案所指出的,==
执行类型转换,但在其他语言和标准中,NaN表示计算失败,出于充分的原因,它本身并不等同。
出于我之外的一些原因,人们认为这是JS的一个问题,但大多数具有替身的语言(即C、Java、C++、C#、Python和其他语言)都表现出了这种确切的行为,人们对此很满意
有时,图像比文字更好,请查看此表(这就是我将其作为答案而不是注释的原因,因为它可以获得更好的可见性)。
在那里你可以看到,只有当类型和内容匹配时,严格的相等比较(==)才会返回true,所以
var f = "-1" === -1; //false
而抽象等式比较(==)只通过转换类型然后严格比较来检查内容*:
var t = "-1" == -1; //true
虽然在没有咨询ECMA的情况下,JavaScript在比较时会考虑什么还不清楚,下面的代码会评估为true。
var howAmISupposedToKnowThat = [] == false; //true
- 这是什么 ==- javascript 运算符
- 我的单元测试选项是什么
- 全局变量和全局对象的属性之间有什么区别吗
- 打破承诺链的好方法是什么
- 在AngularJS应用程序中使用封装指令和路由的推荐方式是什么
- Javascript中的空白是什么
- 是什么让一个“;Uncaught RangeError:超过了最大调用堆栈大小“;错误(Chrome,在其他浏览器中显示
- 在ember/handlers中使用value和valueBinding有什么区别
- JavaScript NaN equvialence
- 什么'在webpack外部设置中,reactDom和reactDom不同
- 在JavaScript中拆分日期字符串的更好方法是什么
- 为什么$.brower被弃用?还有什么更好的替代方案
- nan在C++中是什么意思?为什么pow(-4,-2.1)返回-nan
- NaN 错误代码有什么问题
- JavaScript:什么是 NaN、Object 或 Primitive
- (NaN!=NaN)和(NaN)之间有什么区别
- 我们什么时候能得到"'NaN'不是有效的数值或近似数值.在SQLException异常
- localStorage返回NaN(而不是Number,或者什么都没有)
- 我的代码Javascript出了什么问题?我在警报窗口中收到的消息是NaN
- 为什么 NaN 有用,在什么情况下有用