最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

comparison - Comparing NaN values for equality in Javascript - Stack Overflow

programmeradmin4浏览0评论

I need to compare two numeric values for equality in Javascript. The values may be NaN as well. I've come up with this code:

if (val1 == val2 || isNaN(val1) && isNaN(val2)) ...

which is working fine, but it looks bloated to me. I would like to make it more concise. Any ideas?

I need to compare two numeric values for equality in Javascript. The values may be NaN as well. I've come up with this code:

if (val1 == val2 || isNaN(val1) && isNaN(val2)) ...

which is working fine, but it looks bloated to me. I would like to make it more concise. Any ideas?

Share Improve this question asked Jan 22, 2012 at 22:40 GOTO 0GOTO 0 47.5k25 gold badges138 silver badges164 bronze badges 3
  • 8 Mixing || and && without some parentheses is extremely ugly and confusing. – ThiefMaster Commented Jan 22, 2012 at 22:42
  • 12 NaN and NaN are supposed to be unequal for a reason, because, for example, 0/0 and parseInt("not a number!"), while they both evaluate to NaN, should not be considered equal. – Peter Olson Commented Jan 22, 2012 at 22:44
  • 2 @Peter sometimes this difference is irrelevant to the algorithm. I think this is the case of the OP. – drigoangelo Commented Feb 28, 2014 at 13:11
Add a comment  | 

12 Answers 12

Reset to default 57
if(val1 == val2 || (isNaN(val1) && isNaN(val2)))

Nothing to improve. Just add the parentheses to make it clear to everyone.

Avoid isNaN. Its behaviour is misleading:

isNaN(undefined) // true

_.isNaN (from Underscore.js) is an elegant function which behaves as expected:

// 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

Try using Object.is(), it determines whether two values are the same value. Two values are the same if one of the following holds:

  • both undefined
  • both null
  • both true or both false
  • both strings of the same length with the same characters in the same order
  • both the same object
  • both numbers and
    • both +0
    • both -0
    • both NaN
    • or both non-zero and both not NaN and both have the same value

e.g. Object.is(NaN, NaN) => true

Refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is

if ( val1 === val2 )

If either one or both are NaN it will evaluate to false.

Also, NaN !== NaN

As long as you know these two variables are numeric, you can try:

if (val1 + '' == val2 + '')

It turns the two values into strings. A funny answer, but it should work. :)

NaN is never equal to itself no matter the comparison method, so the only more concise solution for your problem that I can think of would be to create a function call with a descriptive name for doing this rather special comparison and use that comparison function in your code instead.

That would also have the advantage of localizing changes to the algorithm the day you decide that undefined should be equal to undefined too.

And what's about the function Number.isNaN() ? I believe this must be used whenever is possible.

> 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

For Numeric cases the solution is fine but to extend it to work for other data-types as well my suggestion would be as follows:

if(val1 === val2 || (val1 !== val1 && val2 !== val2))

Reason being global isNaN is erroneous. It will give you wrong results in scenarios like

isNaN(undefined); // true
isNaN({});        // true
isNaN("lorem ipsum"); // true 

I have posted a comprehensive answer here which covers the NaN comparison for equality as well.

How to test if a JavaScript variable is NaN

An arrow function can 'unbloat' your conditional and I would use Number.isNaN() instead of isNaN() due to the fact that isNaN() will try to convert the value to a number.

const areEqual = (a, b) => a === b || (Number.isNaN(a) && Number.isNaN(b));

if (areEqual(val1, val2)) {...}

Using isNaN() might lead to the following problems:

let val1 = 'a string';
let val2 = undefined;
let val3 = {};
isNaN(val1) && isNaN(val2) && isNaN(val3); // true
Number.isNaN(val1) && Number.isNaN(val2) && Number.isNaN(val3); // false

isNaN(1n); // Uncaught TypeError: Cannot convert a BigInt value to a number
Number.isNaN(1n); // false

Number.isNaN() - JavaScript | MDN

Why not an if statement like this?

if (isNaN(x) == true){
        alert("This is not a number.");
    }

Equality comparison with NaN always results in False.

We can go for the javascript function isNaN() for checking equality with NaN. Example:

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);
    }
}

Results:

false ---- Values of 0

True ---- Values of 1

Found another way using Array.prototype.includes MDN link. Apparently, [NaN].includes(NaN) returns true for NaN.

function IsActuallyNaN(obj) {
  return [obj].includes(NaN);  
}

Or we can go with davidchambers' solution which is much simpler.

function IsActuallyNaN2(obj) {
  return obj !== obj;
}
发布评论

评论列表(0)

  1. 暂无评论