NaN is mildly mind warping. Can someone explain?

Hi campers,

I was working on Falsy Bouncer and managed to figure it out with the help of MDN https://developer.mozilla.org. I think I understand why the code works but why does NaN not equal NaN?

Why does NaN == NaN or NaN === NaN evaluate to false?

I normally explain it like: So `NaN` is a value JavaScript returns (it isnâ€™t something you would create yourself) when it finds something it expects to be a number but isnâ€™t. So for example:

``````> Math.round('I am a number, honest I am')
NaN
``````

So what it does in that situation is it tries to convert the value to a number and fails. It doesnâ€™t keep any kind of record of what the original value that actually caused the NaN actually is, only that it is `NaN` - the end value is just â€śsomething that should be a number bit isnâ€™tâ€ť. Logically that means there are infinite possiblities as to what it actually is - one `NaN` could be caused by the string `'hello'` interacting with a Math function, and one could be caused by `'7e26ed63-b435-4537-aa73-e8e5d532f863'` and so on, JS has no idea, it only cares that it isnâ€™t a number and it canâ€™t do a calculation. So one `NaN` can never equal another `NaN`; it has no value besides being `NaN` so canâ€™t be compared positively to another `NaN`.

Another way to think of it, leading on from that, is that `NaN` is a description of something that happened, itâ€™s not a value like `1` or `'foo'` that has a concrete representation

1 Like

Itâ€™s kind of like in a story where the hero tells the stupid bad guy â€śMy name is No-manâ€ť and then later when he attacks and all the other bad guys hear the ruckus and go â€śWhoâ€™s attacking you bad guy friend?â€ť and the stupid bad guy is like â€śNo-man is attacking me!â€ť so they say â€śStop screaming then, you idiot.â€ť `Nan` is â€śNo-manâ€ť.

Sorry. I havenâ€™t had coffee yet.

Basically, `NaN` isnâ€™t really a thing that you interact with. Itâ€™s just JavaScriptâ€™s response to being told to do something to not-a-number that can only be done to a number.

Now. Putting all that aside, Iâ€™m going to let you know that you are making this much harder than you need to. This challenge is about teaching you what â€śfalseyâ€ť means. Anything that is â€śfalseyâ€ť will act the same as `false` in a logical condition. It also will return `false` if cast to a Boolean. You donâ€™t need to worry about the list of the 5 values that are falsey and make them be false. Thatâ€™s reinventing the wheel. You can just use the fact that JavaScript already treats these values as `false` in those circumstances.

1 Like

Thanks DanCouper, thatâ€™s a good way to think about it. I guess in other words, this NaN could have been anything, and that NaN could have been anything so really itâ€™d be hard to say they are equal. We donâ€™t know the cause for NaN.

[quote=â€śArielLeslie, post:3, topic:172190, full:trueâ€ť]
Itâ€™s kindâ€¦ `Nan` is â€śNo-manâ€ť. [/quote]

Sorry. I havenâ€™t had coffee yet.

I havenâ€™t yet either as I write this but I did picture this movie called Hollow Manâ€¦

Thanks for the advice. Some food for thought. Iâ€™ll have to go take a second look at my code. It works but thinking about what your saying perhaps I can simplify. This is the code inside the bouncer functionâ€¦ what could I do to simplify?

function filterFalsy(val) {

switch (val){
case â€śâ€ť:
case false:
case 0:
case null:
case undefined:
return false;
default:
return true;
}

}

var notBounced = arr.filter();

return notBounced;
}

Spoiler
``````function bouncer(arr) {
// Don't show a false ID to this bouncer.
return arr.filter((item) => item);
}
``````

Try this in a console:

``````Array(16).join('string' - 1) + ' Batman';
``````
3 Likes

Thanks! That is much cleaner. Iâ€™ll have to read the (item) => item notation. I saw that in the docs but didnâ€™t dig too deep into it. Much appreciated.

Thanks Soupedenuit! Iâ€™ll have to give this a try too. Appreciate the knowledge sharing.

`(item) => item` is the same as `function(item) { return item; }`. Since itâ€™s a filter function it gets treated like `function(item) { return Boolean(item);}`. (Because `filter` is looking at the truthy/falsey-ness of the return value.)

1 Like

The Javascript spec basically says that you should not use == or === to evaluate NaN. Instead use the isNaN() function.

Also bear in mind that NaN is NOT one of the primitive types. It is of type number. So when you have an operation that should return a number but does not, JS can return an entity with the correct type.

1 Like

On a related note, if youâ€™re not familiar with the Number() method it is super useful for when youâ€™re using numbers extracted from strings to do calculations. I often use it to ensure my numbers are numbers, thereby not relying solely on type coercion.

1 Like

Further from what @Soupedenuit said, there is a shorthand that you might see - you can use the unary `+` operator to do the same thing:

``````> Number('123')
123
> +'123'
123
> +'123.456'
123.456
> +'hello'
NaN
``````

It saves quite a bit of typing if you need to ensure a lot of stuff that is coming in as strings get converted to real numbers, which happens in particular when you read values from HTML attributes.

In a related note, if you want to ensure that the numbers are all integers

``````> 1 | 0
1
> 1.234 | 0
1
> '12.34' | 0
12
``````

(this is how the precursor to WebAssembly, ASM (and Emscripten, the C/C++ -> JS compiler, amongst other things), ensures actual integers even though JS only has floating point)

2 Likes

Holy Adam West batman! I see, so because you subtracted 1 from string you performed a mathematical operation on it which should result in a number but itâ€™s not, so NaN.

LOL, thank you. That is quite a few lines of code I didnâ€™t need. I get the falsey <-> filter interaction.

That is correctomendo.