Comparing NaN values for equality in Javascript

2019-01-21 21:41发布

问题:

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?

回答1:

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

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



回答2:

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


回答3:

if ( val1 === val2 )

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

Also, NaN !== NaN



回答4:

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. :)



回答5:

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.



回答6:

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

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

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



回答7:

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



回答8:

I created this answer after reviewing the suggestions of ThiefMaster, Esailija, Joachim Isaksson and davidchambers. Can this be further improved?

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


回答9:

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



回答10:

Why not an if statement like this?

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


回答11:

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



回答12:

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