Unexpected Moments of JavaScript That Will Challenge Your Understanding of the Language
Tags: javascript, programming, webdev, beginners
Published: 2023-03-18 09:32:37

As one of the most popular programming languages in the world, [JavaScript](https://www.javascript.com) is widely used for building dynamic and interactive websites, web applications and even desktop and mobile applications. JavaScript is **a gateway to other web technologies**, because of its widespread use and compatibility with various platforms. It has become a foundational language in modern web development. It is also a complex language with many unexpected moments that can leave even the most experienced developers scratching their heads.

In this article, we'll see various unexpected JavaScript moments that can confuse, test your limits and frustrate you. It will also help you to change the way you code.

Are you ready to make your brain explode🤯? If so, let's enter the jungle..

---
1️⃣
```javascript
2 == [2] // true
```

[`==` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) in JS performs type coercion which means it tries to convert the values being compared to a common data type before making the comparison.

In this instance, the number 2 is converted to a string and the array `[2]` is converted to a string as well. Resulting in both values being `2`. That's why, the comparison evaluates to `true`.

It's generally recommended to use the [strict equality operator `===`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) instead of `==` to avoid unexpected results due to type coercion..

Explore more:
```javascript
'123' == 123        // true 
'foo' == NaN        // false
undefined == null   // true 
NaN === NaN         // false
NaN == NaN          // false
0 == null           // false
```

---
2️⃣
```javascript
[] == ![] // true
```

Comparing an empty array `[]` with a `boolean` value created by negating (using the [`!` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT)) a non empty array `[]`. The result of this comparison is `true`, which might seem unexpected at first glance..

In JS, every value can be either `true` or `false` in a `boolean` context. An empty array is a truthy value, which means it's considered `true` in a `boolean` context. When we apply the `!` operator to it, it's converted to `false`.

On the other side, the `boolean` value created by negating a non empty array is `false`. When we compare an empty array (truthy) with a `false` value (falsy) using the [`==` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality), JS performs type constraint which means it tries to convert the values to a common type before comparing them. So, the empty array is converted to `false` which results in both sides being `false`. At the end, the comparison returns `true`.

Explore more:
```javascript
['a', 'b'] !== ['a', 'b']   // true
['a', 'b'] == ['a', 'b']    // false
[1, 2] + [3, 4]             // "1,23,4" 
```

---

3️⃣
```javascript
null == undefined // true
```
The [double equals `==` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) is used to compare two values for equality, while ignoring their data type. When comparing the values `null` and `undefined` using the double equals operator they are considered equal and the result of the comparison will be `true`. This is because both `null` and `undefined` represent a lack of a value and are so equivalent to each other in this context.

With strict equality operator:
```javascript
null === undefined // false
```

---

4️⃣
```javascript
typeof NaN   // number
typeof null  // object
```
In JS, [typeof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) is an operator used to determine the type of a value or variable.

[NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN) stands for **Not a Number** and is a special value in JS that represents an `undefined` or `unrepresentable` numerical value.

When you use `typeof` with `NaN`, it will return `number`. This might seem strange but it's because `NaN` is technically a numeric data type in JS even though it represents something that isn't actually a number.

When `typeof` is applied to `null`, it returns the string `object`. This is because `null` is considered to be a special value that represents an empty object reference. `null` is not an object itself but rather a primitive value. This is considered to be a quirk or oddity in the language design of JS.

Explore more:
```javascript
typeof function(){}     // "function"
null instanceof Object  // false
```

---

5️⃣
```javascript
true == "1"  // true
false == "0" // true
```

JS converts the string `1` to the `boolean` value `true` and string `0` to `false` because any non empty string is considered _truthy_ and on other side _falsy_. So, the comparison becomes `true == true` which is `true` and `false == false` which is `true`.

Explore more:
```javascript
1 + true      // 2
1 - true      // 0
'' == false   // true
0 == false    // true
true + false  // 1
```

---

6️⃣
```javascript
"1" + 1    // "11"
2 + "2"    // "22"
"5" - 3    // 2
```

When you use the [+ operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Addition) with a `string` and a `number`, the number is converted to a string and concatenated to the string.

If the `string` can be parsed as a `number`, it will [subtract](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Subtraction) the `number` from the `string`.

So,
`"1" + 1` becomes the string `"11"`
`2 + "2"` becomes the string `"22"`
`"5" - 3` becomes the number `2`

Explore more:
```javascript
+"1"                  // 1
-"1"                  // -1

+true                 // 1
-true                 // -1

+false                // 0
-false                // -0

+null                 // 0
+undefined            // NaN

1 / "2"               // 0.5
"2" / 1               // 2

1 / 0                 // Infinity
-1 / 0                // -Infinity

3 * "abc"             // NaN

true > false          // true  

undefined + 1         // NaN
undefined - 1         // NaN
undefined - undefined // NaN
undefined + undefined // NaN

null + 1              // 1
null - 1              // -1
null - null           // 0
null + null           // 0

Infinity + 1          // Infinity
Infinity - 1          // Infinity
Infinity - Infinity   // NaN
Infinity + Infinity   // Infinity
Infinity / Infinity   // NaN
```

---

7️⃣

```javascript
"b" + "a" + + "a" + "a" // "baNaNa"
```
It concatenates the string `b`, the string `a`, the string resulting from the expression `+"a"` and the string `a`.

`+"a"` force the string `a` into a number which evaluates to `NaN` (Not a Number) because `a` is not a valid number.

When we concatenate `b`, `a`, `NaN` (represented as an empty string) and `a`, we get the string `baNaNa`.

---

8️⃣
```javascript
!{}       // false
{} == !{} // false
{} == {}  // false
```

When, we are comparing an empty object `{}` to a negated empty object `!{}`. The exclamation mark `!` is a logical operator that negates the value of the object so `!{}` returns `false` since an object is considered truthy in JS. We are actually comparing `{}` to `false` which results in a `false` value since they are not equal in value or data type.

In the last expression, we are comparing two empty objects `{}`. Despite the fact that they may appear to be identical, they are two separate objects with distinct references in memory so they are not equal in value or data type. In the end the comparison also results in a `false` value.

When you use the **[plus operator +](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Addition)** between two objects wrapped in curly braces `{}`, it tries to concatenate the objects as strings.

Explore more:
```javascript
{} + [] === ""  // false
!!{}            // true 
!![]            // true 
[] + []         // ""
[] + {}         // "[object Object]"
{} + []         // "[object Object]"
{} + {}         // "[object Object][object Object]"
[] == false     // true
!!''            // false
!!0             // false
!!null          // false
!!undefined     // false 
```

---

9️⃣
```javascript
7 > 6 > 5 // false
```

First, `7 > 6` evaluates to `true` because 7 is greater than 6.
Next, `true > 5` is evaluated. In JS, `true` is force into the number `1` and `false` is force into `0`. So `1 > 5` is `false`, since `1` is not greater than `5`.

So at the end, `7 > 6 > 5` is equivalent to `true > 5` which is `false`.

Explore more:
```javascript
5 < 6 < 7  // true
0 > null   // false
```

---

1️⃣0️⃣
```javascript
Math.max() // -Infinity
Math.min() // Infinity
```

`Math.max()` & `Math.min()` are functions that can be used to find the largest and smallest values in a set of numbers respectively.

When called without any arguments, `Math.max()` returns `-Infinity` which represents the smallest possible `number` in JS, on other side, `Math.min()` returns `Infinity` which represents the largest possible `number` in JS.

This behavior makes sense because if there are no numbers provided, there is no largest number to return for `Math.max()` and following same way, there is no smallest number to return for `Math.min()`

---

1️⃣1️⃣
```javascript
parseInt('08')       // 8
parseInt('08', 10)   // 8 
parseInt('0x10')     // 16 
```

`parseInt('08')` converts the string `08` into the integer number `8`. If you were to write `parseInt('08', 10)`, the function will still return `8`.

The reason behind this is because the second parameter of `parseInt` function is the radix which specifies the numbering system to be used. Let's say: `binary`, `octal`, `decimal`, `hexadecimal` etc.. If the radix is not specified `parseInt` will try to detect the radix based on the string format. In above case, `08` is considered an octal number because it starts with `0` so it gets converted into `8` as a decimal number.

`parseInt('0x10')` converts the `hexadecimal` string `0x10` into the integer number `16`. The radix is not specified either, but the prefix `0x` indicates that the number should be treated as a `hexadecimal` number so it gets converted into `16` as a decimal number.

Explore more:
```javascript
parseFloat('3.14.15')  // 3.14 
parseFloat('0.0')      // 0 
```

---

1️⃣2️⃣
```javascript
(function(x) { delete x; return x; })(1);   // 1
```

An anonymous function that takes an argument `x`. Inside the function it tries to delete the `x` variable which is not possible because `x` is a function argument and cannot be deleted. The function then returns the value of `x`.

When this function is called with the argument `1`, the value of `x` inside the function is set to `1`. In this case, the delete operation has no effect, the function simply returns the value of `x` which is `1`

---
1️⃣3️⃣
@tohodo from the DEV Community had a great point to add to this article. Let's see..

```javascript
for (var i = 0; i < 3; ++i) {
  setTimeout(() => console.log(i), 1000); // returns 3 three times
}

for (let i = 0; i < 3; ++i) {
  setTimeout(() => console.log(i), 1000); // returns 0 1 2
}
```

This is because `var` creates a single binding at the function scope, so after a one-second timeout the loop has already run its course, hence you get `3` three times. By using `let` you bind the variable at the block scope (loop), so it returns the values you expected since `i` refers to the value at that loop iteration.

Thanks to @tohodo for sharing this insight.

---

> Great job exploring and understanding these JavaScript concepts!!! This knowledge will definitely help you in interviews and enable you to assess the skills of potential candidates as an interviewer. Keep up the good work and continue learning something Ctrl+N

---

## **❤ Motivation:**

![Motivation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c20q67uc8b81upd3wf8f.png)

---

## **🍀Support**

Please consider following and supporting us by subscribing to our channel. Your support is greatly appreciated and will help us continue creating content for you to enjoy. Thank you in advance for your support!

[YouTube](https://youtube.com/@codeofrelevancy)
[Discord](https://discord.com/invite/f8jwnzcRz2)
[GitHub](https://github.com/codeofrelevancy)


![Dour Darcel #8740](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsv8xbdacnu7pg0s37w0.png)