42
  1. Why NaN === false => false, isn't NaN falsy?
  2. Why NaN === NaN => false, but !!NaN === !!NaN => true

I've been racking my brain trying to figure this out.

alex
  • 479,566
  • 201
  • 878
  • 984
sc1013
  • 1,068
  • 2
  • 16
  • 24

7 Answers7

51
  1. Falsy and being strictly equal to false are very different things, that's why one has a y instead of an e. ;)
  2. NaN is spec'd to never be equal to anything. The second part of your question is comparing false === false, which is funnily enough, true :)

If you really want to know if something is NaN, you can use Object.is(). Running Object.is(NaN, NaN) returns true.

alex
  • 479,566
  • 201
  • 878
  • 984
  • 2
    woow! Did not know this (NaN === NaN) === false – Cacho Santa Nov 07 '15 at 01:59
  • 8
    And (NaN !== NaN) returns true. NaN is the only JavaScript value unequal to itself. – jkdev May 18 '16 at 21:05
  • 1
    NaN isn't a value then, for any purpose really. – 3Dom Feb 14 '18 at 05:27
  • @3Dom It's only purpose is to show that there was a computation error. But yes, it is weird. And in light of how `NaN` behaves it is also kind of weird that this *is true*: `Infinity === Infinity`. – Nux Oct 19 '18 at 09:24
  • "Falsy and being strictly equal to false are very different things" is really an important concept – Chris Perry May 20 '22 at 23:03
19

1.Why NaN === false => false, isn't NaN falsy?

The term "falsy" isn't defined in ECMA-262, it's jargon for where type conversion coerces a value to false. e.g.

var x = NaN;

if (!x) {
  console.log('x is "falsy"');
}

The strict equality operator uses the Strict Equality Comparison Algorithm which checks that the arguments are of the same Type, and NaN is Type number, while false is Type boolean, so they evaluated as not equal based on Type, there is no comparison of value.

2.Why NaN === NaN => false, but !!NaN === !!NaN => true

Because the strict equality comparison algorithm states that NaN !== NaN, hence the isNaN method.

Using ! coerces the argument to boolean using the abstract ToBoolean method, where !NaN converts to true and !!NaN converts to false, so:

!!NaN === !!NaN  -->  false === false  -->  true

Note that the abstract equality operator == will coerce the arguments to be of the same Type according to the rules for the Abstract Equality Comparison Algorithm. In this case, NaN is Type number, so false is converted to a number using toNumber which returns 0. And 0 is not equal to NaN so:

NaN == false  -->  NaN == 0  -->  false
RobG
  • 142,382
  • 31
  • 172
  • 209
7

This condition:

NaN === false

Is always false because numbers are not booleans. To test if a value is falsy you can use a ternary expression:

NaN ? "truthy" : "falsy" // falsy

Why NaN === NaN => false

This is explained in MDN; pragmatically speaking, though, two values of which you only know they're not numbers can't logically be the same thing.

... but why is !!NaN === !!NaN => true

This is because casting NaN into a boolean will make it false and booleans can be compared as per normal.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • its pretty crazy how `NaN == false returns false` but `NaN ? 'truthy' : 'falsey' returns 'falsey'` – maxwell Mar 24 '17 at 04:11
  • 1
    @maxwell—not really. 1. Per [*ECMA-262*](https://262.ecma-international.org/#sec-numeric-types-number-equal) given `x == y` if either *x* or *y* are *NaN* the result is *false* (*NaN* is not `==` or `===` to any value, even *NaN*). 2. The [*conditional operator* `? :`](https://262.ecma-international.org/#sec-conditional-operator) first coerces the conditional expression (i.e. *NaN*) to boolean using [*ToBoolean*](https://262.ecma-international.org/#sec-toboolean), and `ToBoolean(NaN)` returns *false* so the result of evaluating the right hand expression (i.e. the "falsey" one) is returned. :-) – RobG Oct 20 '21 at 12:28
0

=== compares both type and value.

Even though NaN is falsey, === wouldn't be the way to compare it. Something is "falsey" if it evaluates to false in a boolean expression. That isn't the same as being equal to (or equivalent to) false.

For example, null == false returns false, even though null is falsey. This is not completely intuitive, but that's just how JavaScript handles false/falsey values.

0 and the blank string ("") are special cases where value equality comparisons against false evaluate to true (i.e. 0 == false and "" == false). However, 0===false and ""===false still returns false.

NaN is special in that it doesn't have a real value, so comparing it to itself doesn't return true. Essentially, NaN is equal to nothing, not even NaN.

The only way to reliably compare something to NaN is using isNaN( value ).


To your second point, !value is a boolean expression. value first undergoes type coercion to a boolean (and remember, NaN is falsey) and then the boolean NOT ! makes it true. As it happens, it's double negated, so !!NaN is the same as boolean false. Of course false === false, so the expression evaluates to true.

nbrooks
  • 18,126
  • 5
  • 54
  • 66
0
  1. Why NaN === false => false, isn't NaN falsy?

NaN as you are using, is a global property initialized with value of Not-A-Number. It's not boolean. It's NaN data type as defined by IEEE 754.

It's the "same thing" you compare null === false (or even null == false).

In this case, there is no difference using sctric equal or not: NaN == false, also will return false!

  1. Why NaN === NaN => false, but !!NaN === !!NaN => true

2.1. NaN ==== NaN, is false by definition.

2.2. But in !!NaN === !!NaN, you aren't comparing NaNs anymore, when you do ![value], you "evaluate" it (or cast to a boolean).

I'm gonna now explain with null, because it's more used, so you can apply it to NaN:

Casting NaN, it's the same thing that casting null.

null == false? true : false     // false! because it's not a bool false.<br>
!null? true: false              // true! because !null -> true -> if(true)...

More Refs:

http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.1.1
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN

Andre Figueiredo
  • 12,930
  • 8
  • 48
  • 74
  • *NaN* is initialised with the [*IEEE 754 “Not-a-Number” value*](http://ecma-international.org/ecma-262/5.1/#sec-4.3.23), which allows for different types of NaN. – RobG Mar 24 '14 at 03:25
  • ...so? just as I said: `global property initialized with value of Not-A-Number` – Andre Figueiredo Mar 24 '14 at 03:41
  • [to ECMAScript code, all NaN values are indistinguishable from each other.](http://www.ecma-international.org/ecma-262/5.1/#sec-8.5) – Andre Figueiredo Mar 24 '14 at 03:44
  • Yes, it's just that your answer could be read as the value being the string "Not-a-Number" rather than a value that represents not being a number. Nit–picking maybe… :-/ – RobG Mar 24 '14 at 06:26
  • ah! didn't see that misspelling.. thanks! I've improved the answer! – Andre Figueiredo Mar 24 '14 at 11:50
0

This comparison also returns false:

const x = NaN
const y = x

console.log(x === y) // false
AliN11
  • 2,387
  • 1
  • 25
  • 40
-3

NaN and false are both the subset of Falsy.

  • NaN == false -> they're both falsy -> thus 'TRUE'
  • NaN === false -> they're NOT the same type -> thus 'FALSE'
bagz_man
  • 555
  • 2
  • 8
  • 20