Little Shenanigans of JavaScript - Max is Negative Infinity? WHAT!
Tags: javascript, webdev, beginners, codenewbie
Published: 2020-05-15 18:22:04

JavaScript is like the father who over-pampered and spoilt his son, and now the son blames his Dad for things he can't handle. When I was first introduced to JS, I was said, and I quote - *"JavaScript is a very forgiving language."* This epithet stuck with me forever. Indeed, JS lets you do stuff you cannot imagine with other popular languages (I do not speak for the ones I don't know). 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7jzf2f3mjsl4ne6vf3mo.jpg)

But before blaming JS think for a second, WHY would you want to add a string and number? What's the meaning of subtracting two strings? Why would you want to assign a negative index in an array? (Wait, did I just say negative indices??👻 Boo! I will get to it.) Some of the answers are obvious to ardent JS users when they use it day-in and day-out. But for the rest of you out there, just don't do it until you see why! 

Jokes aside, I present to you few more such playful insanities of JS. I had a fun time fiddling with them, hope you too. Enough said, let's dive in.

### 1. Math.min() and Math.max() Upside-down

Most of us use these two functions in day-to-day basis. It's easiest way to compare a set of N numbers. Let's see what happens when you call them without feeding any parameters. What do you think the output to the following be:
```javascript
console.log( Number.POSITIVE_INFINITY > Math.min() ); //false
console.log( Number.NEGATIVE_INFINITY < Math.max() ); //false
//Damn Son!!
```
First reaction: You kidding me!
But let's go ahead and see what values are we comparing at first place.

```javascript
console.log( Math.min() ); //Infinity
console.log( Math.max() ); //-Infinity
```

Although this feels very counterintuitive to have `min()` as `+Infinity` and `max()` as negative, I find an explanation very convincing...

Let's take `Math.min()`. 
We use it to find the minimum number from a set. When you call it with no parameters, it initializes a number with *Maximum Possible Value*. Then, when you compare your first finite number with this, it will always pick that number as minimum. 
Imagine if `Math.min()` was -Infinity. No matter what you compare this with, it will always pick your -Infinity. The function would fail! 

When I have to write an algorithm to find a minimum of something. Say, a minimum Sum, or the smallest number in a dynamic array, or what-so-ever, I always initialize my comparison variable with `Math.min()`, so when I revisit it, I instantly know what I am intending to do! That is, find the MINIMUM. 

Doesn't sound so counterintuitive now, does it? Simple logic- Want to find the minimum of a lot? Initialize using min!

Needless to explain, the same logic goes with `Math.max()`. To check if a number is maximum, we start comparing it with -Infinity and climb all the way up. 

Now that you know, you will find yourself using this so very often! Been there. Done that.

### 2. Identity Crisis of NaN (I am Not-A-Number!!)

What do you think is the type-of NaN?
```javascript
console.log( typeof NaN );
//"number"
```
This one got me rolling on the floor. 🤣
Literally, the full-form of NaN is **Not a number**. And yet, here we are!

Contrary to the popular belief, `NaN` is not a JS Keyword. It is merely a property of the global object *Number*, just like several others you would be aware of: 

```javascript
let x = Number.NaN; //NaN
let y = Number.NEGATIVE_INFINITY; //-Infinity
let z = Number.MIN_VALUE; //5e-324
let w = Number.MAX_VALUE; //1.7976931348623157e+308
```

NaN signifies quite a variety of scenarios. To enumerate a few:
1. You did an operation not explained by Math. 
Example- 0/0, Infinity/Infinity, Infinity * 0
2. You are trying to convert a non-numeric value to Number. 
Example- `Number('foo')` or `+"foo"`
3. You challenged the finites of [Computer Arithmetic](https://www.sciencedirect.com/topics/mathematics/computer-arithmetic) and executed an operation far bigger than the bits could hold. Example- 
`(3.3489324884 * 10e616) / (3.3489324884 * 10e616); //NaN`

So, NaN does not always signify Not-a-number, rather it's a way of saying- 
*"You are trying to get a number beyond the understanding of your machine."* 

having understood NaN now, what would be output for this:
```javascript
let x = (3.454*10e500)/(3.454*10e500);
console.log( x );
console.log( x === NaN );
```
YES! Although x is NaN, the comparison throws **False**. Could you try reasoning out why? 
This question reminds me of a famous John Green quote: 
*"Some infinities are bigger than other infinities."* 

Anyways, if you are searching for an exact answer why this doesn't work and how else will you check for NaN, you will find the answer [here](https://javascriptrefined.io/nan-and-typeof-36cd6e2a4e43).

Shhh, spoiler:
```javascript
let x = NaN;
isNaN(x); //true
```


### 3. Who murdered my Array?

Prepare to get Bonkers! I urge you to open your Developers Console even before you start scrolling, you are going to need it.

```javascript
let x = [10, 20, 30, 40, 50];
console.log( x.length );

x[-1] = 0;
x[-2] = -10;
console.log( x.length );
console.log( x );
``` 
Did JS just let me add negative indices to an array!!! 🔪🔪🔪

Before I start explaining, let's see what the output looks like?

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/8vhzbtloxivwmjrf4a3n.JPG)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2gigatyy5d6mbgauukna.JPG)

If you notice, even after adding two more data to the array, `x.length` remains as 5, although the array shows the newly added data. 

Let's get our funda clear- 
> Any non-primitive data type in JS is treated as an Object. Let alone Arrays, Sets, Maps, even Functions are Objects. And any object is a set of key-value of pairs. 

To understand what's happening in our use case here, let's for a second, forget that **x** is an Array, and treat it as an Object (which it is, since arrays are also objects). Now, let's try adding a function definition, or a new attribute to **x**:

```javascript
x.foo = () => console.log('in x foo')
x.name = "James Dean";
console.log( x );
console.log( x.length );

x.foo();
console.log( x["name"] );
```
I hope you are trying this out on-hands with me. You will get an **x** that looks like this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6whwyfwzso6rtwt2hm8f.JPG)

Are you able to guess what's happening? The array length still remains as 5 but all other attributes are present just like in an Object. If you open up the `__proto__` of **x** you will see *Array*, open it up one more hierarchy and you see *Object*. This is **Prototype Chaining**. 

Since, only whole number indices are supported by the Array data structure, the rest of the *keys* are simply treated as key-value pairs of an Object.

You can simply invoke *foo* using `x.foo()` or access the `name` attribute using one of the two ways of accessing a JSON Object:
1. `x.name` 
2. `x["name"]`

####So what's with the negative indices? 

They are also just a key-value pair like `name`. Where the object **x** has 
`x["-1"]` attribute value. It is only an illusion of negative index where as it's only a part of the **x** object and not the Array. 

And there's your answer!!! 🦄

But before I end, I want you to try a couple more things and see what **x** looks like and what happens to the *length*:

```javascript
x[5] = 90;
x[8] = 100;
//NOTE: We skipped index 6 and 7 altogether.
//What happens to the length?

console.log( x.length ); //9
console.log( x );
```

When you skip the whole number indices (the legit indices of an array), JS just creates EMPTY spaces- an array index holding *undefined* data type. But the space gets reserved as a part of the array. And that's why the length increases to the maximum index. This is what it looks like:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7fmrhzfcaaog7nidx7sr.JPG)

AMAZING!!! Isn't it?

I absolutely adore JavaScript for it's Willy Wonka ways with data types and data structures. I have laughed out loud at some problems, I have pulled my brains out at others. But nevertheless, I hope this language never dies. Frameworks may come and frameworks may go, I hope Vanilla JS goes on forever. 

I do hope you had fun trying out some examples from above. And I also hope, I atleast inspired a handful of you to open up your computers and get scripting! Do let me know if I went wrong somewhere or what you think about the article. Your response inspires me to write more! 🧐 

Find the previous article of this series [here](https://dev.to/salyadav/little-shenanigans-of-javascript-4e0j).
See you soon! 👋