6 JavaScript WTFs and what to learn from them
Tags: javascript, node, beginners, computerscience
Published: 2019-07-29 10:55:24

Hi! I'm sure that in your JavaScript developer journey you saw at least once *(per day)*  **‘undefined’ is not a function** or you asked yourself why **the type of the NaN is actually a number.** Well, sometimes JavaScript wants to put you to the pressure test.
	![Gordon Ramsay angry](https://media.giphy.com/media/l41Yb2wVzu9vmumZi/giphy.gif)

In this article, you will be part of an adventure in the funny *(and dark)* side of this beautiful programming language. Let's start!
___

## 1. Min > Max
```javascript
Math.min() > Math.max() //true
```
## Explanation:
Ok, so first let's define a couple of things.

> - **`Math`** is a built-in object that has properties and methods for mathematical constants and functions. Not a function object.
> - The static function **`Math.max()`** returns the largest-valued number passed into it, or [`NaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN "The global NaN property is a value representing Not-A-Number.") if any parameter isn't a number and can't be converted into one.

Perfect, until now we know what the Math object represents in JavaScript and what the **.max()** static function does. Similarly, the **.min()** function will do the opposite operation. Until now our instinct may say that *Math.max()* should return the **Number.MAX_VALUE** if no parameters are provided.

However, that assumption would be erroneous. Here's why. Imagine that you will have to implement a function that finds the **maximum value from an array**. That's easy! The simplest way to do it is to iterate through the entire array, compare the elements and *store the maximum value*. Here's the twist! That variable where you store the maximum value should be initialized with a **very, very small value**, the smallest.

You might think by now that, ok, the smallest value in Javascript is **Number.MIN_VALUE (5e-324)** and you are right. But, JavaScript has something prepared for you in this particular case and that is **Infinity**.
> The global [`Infinity`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity "The global Infinity property is a numeric value representing infinity.") property is a numeric value representing infinity.

And finally, full description of *.max()* function:

> Math.max() returns the largest of the given numbers. If any one or more of the parameters cannot be converted into a number, [`NaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN "The global NaN property is a value representing Not-A-Number.") is returned. The result is [`-Infinity`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity "The global Infinity property is a numeric value representing infinity.") if no parameters are provided.
> 
```javascript
Math.min() > Math.max() -> Infinity > -Infinity //true
```
### Takeaways:
- What is **Math** object
- How **min()** and **max()** functions behave
- **Infinity** object in JavaScript


## 2. 0.1 + 0.2 = ?
Well, that's too easy. 0.1 + 0.2 = 0.3, right? Not in JavaScript! *(or JAVA, or C++, or C#, or..you got the point)*
```javascript
0.1 + 0.2 === 0.3 //false
```
![Intense calculations](https://media0.giphy.com/media/3o7btPCcdNniyf0ArS/giphy.gif)
## Explanation:
How is this possible? Before you reconsider all the basic math that you learned, let me introduce [Floating Point Math](http://0.30000000000000004.com/).

> Computers can only natively store **integers**, so they need some way of representing decimal numbers. This representation comes with some degree of **inaccuracy**.

This subject's a complex one and needs some serious number of hours invested in it. However, I will try to simplify it for this particular situation.

In the case of **base 10 system**, the only fractions that can be expressed cleanly are the ones with prime factor as a base *(&frac12;, &frac14;, 1&frasl;5, etc.)*. In comparison 1&frasl;3 has **repeating decimals** *(0,33333..)*. Now if we take this information and apply it for **2 base system**, the clean fractions are *&frac12;, &frac14; and 1&frasl;8*, while *1&frasl;5 and 1&frasl;10* have repeating decimals. That's causing some leftovers in this example.
```javascript
0.1 + 0.2 === 0.30000000000000004 //true
```
> When you do the math on these repeating decimals, you end up with **leftovers** which carry over when you convert the computer's base 2 (binary) number into a more human-readable base 10 number.

### Takeaways:
- **Floating Point Math** overview
- This concept applies to *most of the programming languages*

## 3. baNaNa
Good, after that hard mathematical problem, let's do something fun!
```javascript
"b" + "a" + +"a" + "a" -> baNaNa
```
## Explanation:
Different from the other 2 WTFs, this one is a little bit simpler. That's because you have 75% of the problem solved. Now we have just one tiny aspect to clarify: what **+ +"a"** will return.

JavaScript syntax is valid because the second **+** is not the addition operator, but a **unary operator**.

> The **[unary +](https://www.ecma-international.org/ecma-262/#sec-unary-plus-operator)** operator converts its operand to Number type. Any unsupported values will be evaluated to `NaN`.

That was effortless! So our expression will l as below, because **"a"** can't be converted to a Number.
```javascript
"b" + "a" + NaN + "a" -> baNaNa
```
In order to conclude we should confirm one more piece of the puzzle. What **String + String + NaN + String** will return? How the addition operator will behave?
> The **[addition operator](https://www.ecma-international.org/ecma-262/#sec-addition-operator-plus)** either performs string concatenation or numeric addition.

So, there are two types of addition that can occur, **string concatenation** or **numeric addition**, in this particular order. The way the algorithm work is the following: 

Transform the operands into primitives using **[ToPrimitive()](https://www.ecma-international.org/ecma-262/#sec-toprimitive)** function. 

If one of the operands is a **String**, then transform the other one into a String and perform *string concatenation*. Otherwise, convert both of them to **Number** and execute *numeric addition*.
```javascript
"b" + "a"-> "ba"
"ba" + NaN -> "ba" + "NaN" -> "baNaN"
"baNaN" + "a" -> "baNaNa"
```
### Takeaways:
- What is **Unary operator**
- Addition operator *algorithm*
- **ToPrimitive()** function and one use case for it

## 4. Initialization before the declaration?
Take this code for example:
```javascript
message = "don't forget to hit the heart button if you liked it.";
console.log(promoteArticle("Stranger"));
function promoteArticle(name) {
	return `${name}, ${message}`;
};
var message;
```
What will be prompted in the console? A **ReferenceError** that message is not defined? Or maybe the string **"Stranger, undefined"**. No, it must be a **TypeError**, promoteArticle is not a function.

Fortunately for us, the output will be exactly what we wanted: *"Stranger, don't forget to hit the heart button if you linked it"*. But why? The **"Hoisting"** *(buzzword)* JavaScript behavior is responsible for that.

> Hoisting is JavaScript's default behavior of `moving declarations to the top`.

*Note: This is available only for variables defined with the var keyword and declared functions.*

Using this piece of information we can claim that our code will look like this after **compilation**:
```javascript
function promoteArticle(name) {
	return `${name}, ${message}`;
};
var message;
message = "don't forget to hit the heart button if you liked it.";
console.log(promoteArticle("Stranger"));
```
Let's take it step by step. The **promoteArticle() function** is on the top because function declarations are the **first** elements moved to the top, followed by var variable declaration.

Also, no error is thrown and the message has the right value is because by the time the function is invoked, the variable was both **declared** and **initialized**.

Just to make sure I didn't cause any kind of confusion, I will mention the difference between **declared functions and expression functions**.  Below is an example containing both types.
```javascript
function declaredPromoteArticle(name) {
	return `${name}, ${message}`;
};
var expressionPromoteArticle = function(name) {
	return `${name}, ${message}`;
}
```
And after compile:
```javascript
function declaredPromoteArticle(name) {
	return `${name}, ${message}`;
};
var expressionPromoteArticle; // just the variable definition was hoisted
expressionPromoteArticle = function(name) {
	return `${name}, ${message}`;
}
```
### Takeaways:
- What is **Hoisting**
- Function declaration vs function expression

## 5. typeof NaN == 'number'
![God please no meme](https://tilldawngroup.com/wp-content/uploads/2015/04/giphy-1.gif)
This one might appear strange especially because of the lexical side, **"Not a number is a number"**, but it will make sense in a second. First, let's inspect the definition:

> The **global** ``NaN`` property is a value representing Not-A-Number.

A simple and clear definition for NaN, but we can find the trick in the **'global'** word. Contrary to our first instinct, NaN is not a keyword (like null, if, var, etc.), but a **global property**. What global object may include this property? Yes, you guessed it, is the **Number object**.
```javascript
typeof NaN == 'number' -> typeof Number.NaN == 'number' //true
```

> [`Number.MIN_VALUE`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_VALUE "The Number.MIN_VALUE property represents the smallest positive numeric value representable in JavaScript.")
The smallest positive representable number - that is, the positive number closest to zero (without actually being zero).
[`Number.NaN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/NaN "The Number.NaN property represents Not-A-Number. Equivalent of NaN.")
Special "not a number" value.

Why I also extracted the MIN_VALUE property you may ask. It's because it will be clearer why the JavaScript compiler doesn't know any difference between **MIN_VALUE** and **NaN** property, and therefore both types are **numbers**.

### Takeaways:
- NaN it's not a keyword, but a property
- How [type of](https://www.ecma-international.org/ecma-262/#sec-typeof-operator) operator behaves in this case

## 6. Array.prototype.sort()
The subject of the last WTF is the behavior of the **sort()** method, without any parameter sent.
```javascript
[32, 3, 6].sort() //[3, 32, 6]
``` 
Ok, that not work how we expected. Why the values are in that particular order? Let's take **more examples** and be adventurous.
```javascript
[32, 3, true, 6].sort() //[3, 32, 6, true]
[32, 3, true, 6, NaN].sort() //[3, 32, 6, NaN, true]
[32, 3, true, 6, NaN, undefined].sort() //[3, 32, 6, NaN, true, undefined]
``` 
Got it? Yup, the default algorithm **casts** each value into a *string* and then sort them accordingly. 

In order to reach the expected result, sort() method will need **a compare function** as a parameter. That function receives **two parameters** and return a number which describes the *relation between them*. 

> The notation a < b means comparefn(a,  b) < 0; a = b means comparefn(a,  b) = 0 (of either sign); and a  >  b means comparefn(a,  b) > 0.

Below it's an example using an array of users. The sort algorithm is based on the  **age property** of each user.
```javascript
let users = [
	{
		name: "Andrei",
		age: 24
	},
	{
		name: "Denisa",
		age: 23
	}];
users.sort((first, second) => first.age - second.age);
//[ { name: 'Denisa', age: 23 }, { name: 'Andrei', age: 24 } ]
```
### Takeaways:
- **Array.prototype.sort()** default behavior
- How to implement a **specific** sort mechanism

## Bonus: `NaN`  is not a  `NaN`
Surprise, there is more!
```javascript
NaN === NaN //false
```
This one refers to the [Strict Equality Comparison](https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison) and its implementation.

> 1.  If  [Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-data-types-and-values)(x) is different from  [Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-data-types-and-values)(y), return  false. 
> 2.  If  [Type](https://www.ecma-international.org/ecma-262/#sec-ecmascript-data-types-and-values)(x) is Number, then
    1.  If  x  is  ``NaN``, return  false.
    2.  If  y  is  ``NaN``, return  false.
    ...
 > 3.  Return  [SameValueNonNumber](https://www.ecma-international.org/ecma-262/#sec-samevaluenonnumber)(x,  y).
    
   As we know, the NaN type is number so the *second if the condition is matched*. After that, if any of the operands is NaN, **false** is returned.

### Takeaways:
- The first part of **Strict Equality Comparison** implementation
- Last part of that algorithm uses another one named **SameValueNonNumber**

___

Finally, we are done. You might think that those WTFs are **childish** *(and you will be right from some of them)*, but they may hide **small bugs** *(with big impact)* and waste a lot of your time and energy.

Also, the **habit** to search in the official documentation when something seems fishy in your code and learn *how the compiler "thinks"* can really improve your skills.

![Done meme](https://media0.giphy.com/media/8JW82ndaYfmNoYAekM/giphy.gif)

**Note:** *This is my first attempt in writing technical articles. Please let me any kind of feedback in the comments and also what topics are you interested in. Happy coding!*