在 Javascript 中比较 NaN 值是不是相等
Posted
技术标签:
【中文标题】在 Javascript 中比较 NaN 值是不是相等【英文标题】:Comparing NaN values for equality in Javascript在 Javascript 中比较 NaN 值是否相等 【发布时间】:2012-02-16 10:22:44 【问题描述】:我需要在 javascript 中比较两个数值是否相等。这些值也可能是NaN
。
我想出了这段代码:
if (val1 == val2 || isNaN(val1) && isNaN(val2)) ...
这工作正常,但在我看来它显得臃肿。我想让它更简洁。有什么想法吗?
【问题讨论】:
在没有括号的情况下混合||
和&&
非常丑陋和混乱。
NaN
和 NaN
应该是不相等的,因为例如,0/0
和 parseInt("not a number!")
,虽然它们都计算为 NaN
,但不应考虑相等。
@Peter 有时这种差异与算法无关。我认为这是 OP 的情况。
【参考方案1】:
if(val1 == val2 || (isNaN(val1) && isNaN(val2)))
没有什么可改进的。只需添加括号以使所有人都清楚。
【讨论】:
我会通过评论来改进它,解释为什么NaN === NaN
应该返回 true。【参考方案2】:
避免isNaN
。它的行为具有误导性:
isNaN(undefined) // true
_.isNaN
(来自Underscore.js)是一个优雅的函数,其行为符合预期:
// Is the given value `NaN`?
//
// `NaN` is the only value for which `===` is not reflexive.
_.isNaN = function(obj)
return obj !== obj;
;
_.isNaN(undefined) // false
_.isNaN(0/0) // true
【讨论】:
isNaN(undefined)
是 true
有什么问题? undefined
不是数字。对您来说,这里似乎有什么误导性?
@trejder:NaN 和 undefined 是不同的值。不同的值类型,甚至。
@davidchambers:是的。这并没有改变事实,undefined
不是 一个数字。这使我们得出一个结论,isNaN(undefined)
应该 返回true
。 NaN
和 undefined
是不同的值和不同的值类型这一事实不会改变我的状态。因为这是完全不同的故事。或者指出我哪里错了。
@trejder:对于 isNaN 应该回答哪个问题,我们有不同的想法。你认为isNaN(x)
应该等价于!isNumber(x)
,而我建议它应该告诉我们 x 的值是否恰好是 NaN。如果想知道一个值是否不是数字,Object.prototype.toString.call(x) !== '[object Number]'
更可取,因为它不允许相互竞争的解释。
@drigoangelo:如果您对编写if (x !== x)
感到自在,并且相信您的团队中所有当前和未来的成员都会理解它的作用,那就太好了。如果不是,最好有一个函数来回答这个问题:这个值是 NaN 吗?不幸的是,内置的 isNaN 不是那个函数。【参考方案3】:
试试Object.is()
,判断两个值是否相同。如果满足以下条件之一,则两个值相同:
undefined
null
true
或两者false
两个字符串长度相同,字符顺序相同
都是同一个对象
数字和
+0
-0
NaN
或既非零又非NaN
且两者具有相同的值
例如Object.is(NaN, NaN)
=> true
参考https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
【讨论】:
现代 javascript 的好答案。请注意,因为0 === -0
返回 true
但 Object.is(0, -0)
返回 false
。对于提问者的用例,您可能需要执行val1 === val2 || Object.is(val1, val2)
。
从来不知道这个+1。谢谢【参考方案4】:
if ( val1 === val2 )
如果其中一个或两个都是NaN
,它将评估为假。
另外,NaN !== NaN
【讨论】:
这不是等价的吗?如果 val1 和 val2 都是NaN
,则 OP 希望表达式返回 true。【参考方案5】:
只要知道这两个变量是数值的,就可以试试:
if (val1 + '' == val2 + '')
它将两个值转换为字符串。一个有趣的答案,但它应该工作。 :)
【讨论】:
它不会总是给出与原始代码相同的结果,但话又说回来,在它会有所不同的情况下,它可能是首选行为。例如" " == 0;
,即true
,但在您的代码中将是false
。这可能被认为是一种改进。【参考方案6】:
无论使用哪种比较方法,NaN 都永远不会等于其自身,因此对于您的问题,我能想到的唯一更简洁的解决方案是创建一个具有描述性名称的函数调用来执行此相当特殊的比较并使用该比较而是在您的代码中运行。
这还具有在您决定 undefined 也应该等于 undefined 的那一天对算法进行本地化更改的优势。
【讨论】:
【参考方案7】:Number.isNaN() 函数又是怎样的呢?我相信必须尽可能使用它。
> NaN === NaN
false
> Number.isNaN
ƒ isNaN() [native code]
> Number.isNaN() === Number.isNaN()
true
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN
【讨论】:
Number.isNaN(NaN) === Number.isNaN(undefined) 解析为假【参考方案8】:对于数字情况,解决方案很好,但要将其扩展为也适用于其他数据类型,我的建议如下:
if(val1 === val2 || (val1 !== val1 && val2 !== val2))
全球isNaN
的原因是错误的。在
isNaN(undefined); // true
isNaN(); // true
isNaN("lorem ipsum"); // true
我在这里发布了一个全面的答案,其中也涵盖了 NaN 比较的相等性。
How to test if a JavaScript variable is
NaN
【讨论】:
【参考方案9】:我在查看了 ThiefMaster、Esailija、Joachim Isaksson 和 davidchambers 的建议后创建了这个答案。可以进一步改进吗?
// Determines if two numeric values are equal.
// Also returns true when both parameters are NaN.
function areEqualNumeric(val1, val2)
return val1 === val2 || (val1 !== val1 && val2 !== val2);
【讨论】:
我想不需要进一步改进,AngularJS 使用完全相同的代码compare = function(a,b) return a === b || (a !== a && b !== b); ;
【参考方案10】:
为什么不用这样的 if 语句?
if (isNaN(x) == true)
alert("This is not a number.");
【讨论】:
这不能回答问题。【参考方案11】:与 NaN 的相等比较总是得到False
。
我们可以使用 javascript 函数 isNaN()
来检查与 NaN 的相等性。
示例:
1. isNaN(123) //false
2. var array = [3, NaN];
for(var i = 0 ; i< array.length; i++)
if(isNaN(array[i]))
console.log("True ---- Values of " + i);
else
console.log("false ---- Values of " + i);
结果:
false ---- 值为 0
真 ---- 值为 1
【讨论】:
【参考方案12】:使用 Array.prototype.includes MDN link 找到了另一种方式。显然, [NaN].includes(NaN) 为 NaN 返回 true。
function IsActuallyNaN(obj)
return [obj].includes(NaN);
或者我们可以采用更简单的 davidchambers 的解决方案。
function IsActuallyNaN2(obj)
return obj !== obj;
【讨论】:
当你在 SO 上写答案时,总是尽量少解释你的代码。 不要仅仅为此构造一个数组字面量。如果要使用 ES6 方法,请使用Object.is(obj, NaN)
以上是关于在 Javascript 中比较 NaN 值是不是相等的主要内容,如果未能解决你的问题,请参考以下文章