What is NaN in JavaScript?
Tags: javascript, webdev, beginners, programming
Published: 2023-01-25 15:56:50

This article is a part of the ReturnTrue series. Here we solve [ReturnTrue puzzles](https://alf.nu/ReturnTrue) and try to explain how we find solutions and why exactly they work.

The goal is not to show the answers but to dive deep into the elaborate internals of JavaScript and browsers. Yet, we recommend you try to find solutions yourself. It would be more interesting this way, be sure.

Now let’s continue our journey and move to the 2nd task and the main topic of this article — NaN.

## Reflexive

```js
function reflexive(x) {
  return x != x;
}
```

If you are an experienced developer, you know the answer:

```js
reflexive(NaN)
```

But there is something to discuss.

## First, why is it “reflexive”?

In a nutshell, a binary relation across a set is [reflexive](https://en.wikipedia.org/wiki/Reflexive_relation) if each element of the set is related to itself.

Math definitions from Wikipedia, brrr. Let’s explain it another way.

Imagine a set of natural numbers. You can take any number and check whether it equals itself or not:


```js
> 1 == 1
true
```

If this check returns `true` for all the natural numbers, then equality is “reflexive” for them.

The same goes for inequality. Inequality is “anti-reflexive” because it’s `false` for all the natural numbers:

```js
> 1 != 1
false
```

But NaN is not equal to itself. It means that for NaN equality is anti-reflexive, while inequality is reflexive. Hence the name.

```js
> NaN == NaN
false

> NaN != NaN
true
```

## Second, how to get NaN in JavaScript?

If we try to make a number from a non-numeric string, JavaScript will not throw an exception. Instead, it will return NaN. It is, well, understandable. But JavaScript is one of the few languages that returns NaN in such a common operation.

E.g. Python throws an exception:

```python
int("a")
```

```shell
$ python nan.py
Traceback (most recent call last):
  File "./nan.py", line 1, in <module>
    int("a")
ValueError: invalid literal for int() with base 10: 'a'
```

PHP returns zero:

```php
<?
$str = "a";
$num = (int)$str;
echo $num;
?>
```

```shell
$ php -f nan.php
0
```

But JavaScript says:


```js
> Number('a')
NaN
```

That’s why every JavaScript newbie knows about NaN. Usually, they do not go further than _"NaN is, eh, when a string to number conversion failed"._ But we will go deeper.

## Going deeper

As you know, when `parseInt` can not do its job, it returns NaN:

```js
> parseInt('a')
NaN
```

So, we have to check the result of such parsing for NaN. There is a global function [`isNaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN), that is available since the first edition of ECMAScript. This function is suitable for this check, but you should not trust it all the time. `isNaN` tries to convert the passed argument to a number before the very check. That’s why `isNaN` returns `true` for any value that it can’t convert to a number:

```js
> isNaN({})
true
```

With this in mind, the standard authors should have named `isNaN` — `canNotBeConvertedToNumber`. To fix this issue, they introduced [`Number.isNaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) in ES6, which works as expected:

```js
> Number.isNaN({})
false
```

Unclear browser API is not the only problem in JavaScript related to NaN. As you also may know, NaN as an operand transforms any arithmetic operation result into NaN:

```js
> 1 + NaN
NaN
```

Plus, NaN does not equal anything, even itself:

```js
> false == NaN
false

> NaN != NaN
true
```

Such behavior is so unique that the spec suggests checking NaN using a strict inequality operation. Like, duck testing:

<blockquote cite="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-isnan-number">
  <p>A reliable way for ECMAScript code to test if a value <code>X</code> is a <code>NaN</code> is an expression of the form <code>X !== X</code>. The result will be <code>true</code> if and only if <code>X</code> is a <code>NaN</code>.</p>
  <p>— <a href="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-isnan-number">18.2.3 isNaN</a></p>
</blockquote>

It’s important to note here that this situation is not the same as we have with objects in JavaScript:

```js
> {} !== {}
true
```

But in this case we’re comparing _two different objects,_ while with NaN we’re comparing the same value.
To make it clear, consider these examples:

```js
> const obj = {}
> obj !== obj
false
```

```js
> const nan = NaN
> NaN !== NaN
true
```

Anyway, aside from those described above, there are plenty of other ways to get NaN in JavaScript. Most of them are not related to arithmetic operations at all. E.g., you can try to get a code of the character of the string outside of the length of this string:

```js
> ''.charCodeAt(1)
NaN
```

Or parse an invalid date string:

```js
> Date.parse('a')
NaN
```

From some perspective, the fact that we get NaN in such cases is okay, but is it? If you can’t get a code of the character of the string, you would like to get an exception signaling the error. But in JavaScript, access to any non-existing element of an array does not lead to an error:

```js
> [1, 2][3]
undefined

> ({})['a']
undefined

> ''[0]
undefined
```

That’s why in our case JavaScript tries to return a “thing”, which is a number and an error at the same time. You know, NaN is a number:

```js
> typeof NaN
"number"
```

----

_Shameless plug you may want to click on:_

[![Look at this](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjlc5at8b4a90hr7h8a1.png)](https://uploadcare.com/docs/)

----

## Going even deeper

The NaN weirdness in JavaScript does not end here.

If we try to get the NaN-th character of the non-empty string, we’ll get it:


```js
> 'a'.charAt(NaN)
"a"
```

It works this way because sometimes JS converts NaN to zero behind the scenes. Surprise!

There are lots of different type conversions described in the spec. One of them is `ToInteger`. JavaScript uses it when a standard function expects an integer argument. Before the use of the passed argument, JavaScript applies `ToInteger` to the value of that argument. If the value is NaN, then `ToInteger` replaces it with zero:

<blockquote cite="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-tointeger">
  <p>2. If number is <code>NaN</code>, <code>+0</code>, or <code>-0</code>, return <code>+0</code>.</p>
  <p>— <cite><a href="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-tointeger">7.1.5 ToInteger</a></cite></p>
</blockquote>

Aside from that, there are more curious cases with NaN. Check this out:

```js
> [1, 2, NaN].indexOf(NaN)
-1

> [1, 2, NaN].includes(NaN)
true
```

`indexOf` can’t find NaN, while `includes` can. Why? Because `indexOf` uses strict equality checks during the search. NaN does not equal itself, so `indexOf` can’t find it.

`includes` search is a bit more complicated. It has an explicit check for NaN for the argument and array values.

Another example is exponentiation which goes nuts when we pass NaN. Yeah, we know that “NaN turns any arithmetic operation into NaN” but for the sake of God, what is going on here?

```js
> NaN ** 0
1
```

It’s a tricky question. Exponentiation in JavaScript does not care what exactly you are trying to raise to the power 0. The result will always be the same:

```js
> ({ wtf: true }) ** 0
1

> (function orly() {}) ** 0
1
```

Honestly, the exponentiation algorithm is not that simple at all:

```js
> (-10) ** 1.2
NaN
```

Here we get NaN not because of JavaScript weirdness, but that’s the story for the next time.

## Wait, but what is NaN, once again?

Oh, glad you asked!

JavaScript implementations are trying to be ECMAScript compliant, right? Let’s check what the spec says about NaN:

<blockquote cite="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-terms-and-definitions-nan">
  <p>Number value that is a IEEE 754 “Not-a-Number” value.</p>
  <p>— <cite><a href="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-terms-and-definitions-nan">4.3.24 NaN</a></cite></p>
</blockquote>

_sigh_

Alright, what is that IEEE 754 thing?

[IEEE](https://en.wikipedia.org/wiki/Institute_of_Electrical_and_Electronics_Engineers) stands for “Institute of Electrical and Electronics Engineers”. It is a professional association that develops engineering standards. In particular, they create standards for telecommunications.

There are IEEE standards for the many things we use daily. E.g. [IEEE 1003](https://en.wikipedia.org/wiki/POSIX) is POSIX, while [IEEE 802](https://en.wikipedia.org/wiki/IEEE_802) is a set of standards describing different networks. In particular, [802.11](https://en.wikipedia.org/wiki/IEEE_802.11) describes wireless communications, in other words — Wi-Fi. Hence the “versions” of Wi-Fi: 802.11a, 802.11b, and so on. All of them are different versions of that standard.

So, [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) is a standard for floating-point arithmetic. It describes the implementation of floating point numbers and operations for them <InlineSpoiler>what those numbers are we will see in the next articles</InlineSpoiler>

Among other things, the standard defines NaN as a special numeric value. Computers should return NaN when they can’t find the operation result. For example, when it’s impossible to compute or the operation itself is invalid.

There are lots of examples of such operations. There are the ones the standard describes:

* 0 by 0 or ∞ by ∞ division;
* 0 by ∞ multiplication;
* getting a reminder of ∞ by 0 division;
* subtraction of infinities of the same sign;
* and so on.

There is NaN in most programming languages because they follow the standard. But not all the operations listed above return NaN in those languages. Some may throw exceptions if the language developers have decided so. Otherwise, NaN is usually used.

For instance, you can not divide by zero in Python:

```python
0/0
```

```shell
$ python zero.py
Traceback (most recent call last):
  File "./zero.py", line 1, in <odule>
ZeroDivisionError: division by zero
```

But you can get NaN by trying to add +∞ to −∞:

```python
float('inf') + float('-inf')
```

```shell
$ python inf.py
nan
```

Go will do the same, while in PHP you may get NaN by trying to get an arccosine of the value out of \[−1; 1\]:

```php
<?
echo acos(2);
?>
```

```shell
$ php -f acos.php
NaN
```

The same is true for C.

As you see, programming languages work with NaN in varied ways. They may not even use NaN in arithmetic. They may throw exceptions in “critical” cases and return defaults in the others.

But some languages use NaN for all the awkward cases. JavaScript is one of those languages.

NaN and floating-point arithmetic are extensive and intriguing topics. But that’s all for today, folks!

If you wish to continue the journey, here is the cliffhanger. There is not one NaN for “all the weirdness”. IEEE 754 defines two of them: quiet NaN and signaling NaN. Happy research! 

_Originally published by Igor Adamenko in [Uploadcare Blog](https://uploadcare.com/blog/what-is-nan/)_