JS Equality in-depth
Published: 2022-03-25 20:45:18

Hey All 👋

We are often asked what's the difference between **==** and **===**,
And the most common answer we have is **==** does **loose comparison** or it ignores types while comparison and **===** does **strict comparison** or it doesn't ignore types while comparison. But there is more to that and in this article we will discuss in detail about Equality operators in JavaScript.

---

## Double & Triple Equals

Let's talk about both of them one-by-one with their algorithms :-

### Strict Equality Comparison ( === )

The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:

![Strict Equality Comparison](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs1d64lyf0esmm3vpu4y.png)
 
**1)** If we are comparing two values and both of them have **different types**, it'll not do any comparison and simply returns **false**.

**Example :-** 

```javascript
1 === "1" // false
1 === true // false
1 === undefined // false
1 === [1] // false
```

**2)** If **typeof(x)** is **Number** then :-

**a & b }** If any of x or y is **NaN** then it returns **false**.

**Example :-** 

```javascript
1 === NaN // false
NaN === 1 // false
```

**c }** If x and y has the **same number value** then it returns **true**.

**Example :-** 

```javascript
123 === 123 // true
12.3 === 12.3 // true
0.2 === 0.2 // true
```

**d & e }** If x is **+0** and y is **-0** or vice-versa it returns **true**.

**Example :-** 

```javascript
+0 === -0 // true
-0 === +0 // true
```

**f }** else returns **false**.

**Example :-** 

```javascript
1 === +Infinity // false
1 === -Infinity // false
```

**3)** When neither x nor y are number values then comparison is performed as follows:
 
![Same Value Non Number](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efj37erfblqu7200zywk.png)

**1 & 2 }** Conditions - typeof(x) is **not Number** and typeof(x) is **same** as typeof(y).

**3 & 4 }** If typeof(x) is **Undefined** or **Null** then it returns **true**.  

```javascript
null === null // true
undefined === undefined // true
null === undefined // false as typeof(null) is not same as typeof(undefined)
```
**5 a}** If typeof(x) is **String** also x and y are exactly the same sequence of code units then it returns true otherwise false.

**Example - *

```javascript
"alok" === "alok" // true
"alok12" === "alok12" // true
"alok" === "Alok" // false
```

**6 a}** If typeof(x) is Boolean and if both x and y are true or both are false it returns true otherwise returns false.

**Example -**

```javascript
true === true // true
false === false // true
true === false // false
```

**7 a}** If typeof(x) is Symbol and if both x and y are same symbol value it returns true otherwise it returns false.

**Example -**

```javascript
let a = Symbol('hey');
let b = Symbol('hey');
let c = a;

a === b // false
a === c // true
a.description === b.description // true
```

Here we have created two symbols **a** and **b**, though they look the same but have different values, and comparing them returns **false**. **a** and **c** point to the same symbol value thus comparing them returns **true**. Also, the values of descriptions of **a** and **b** are the same thus comparing them returns **true**.

**8 }** If x and y are the same object value, then it returns true. Otherwise, it returns false..

**Example -**

```javascript
let a = {a:1};
let b = {a:1};
let c = a;

a === b // false
a === c // true
a.a === b.a // true
```



Here we have created two objects **a** and **b**, and similar to symbols, though they look the same but have different values, and comparing them returns **false**. **a** and **c** point to the same object value thus comparing them returns **true**. Also, the values of property (**a**) of object **a** and **b** are the same thus comparing them returns **true**.

### Abstract Equality Comparison ( == )

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

![Abstract Equality Comparison](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9gu9jutrmrbue3tay5jr.png)

**1)** If **x** and **y** both are of same type then it'll do the **===** operation on them.

**2 & 3)** If **x** is **null** and **y** is **undefined** or vice-versa it returns **true**.

**Example -**

```javascript 
null == undefined // true
undefined == null // true
```
 
**4 & 5)** If one of the values is **number** and the other is **string** then **==** prefer **numeric comparison** i.e. coerce string to number.

**Example -**

```javascript
Number("2") // 2
Number("A") // NaN

2 == "2" // 2 == 2 -> true
"4" == 4 // true
2 == "3" // 2 == 3 -> false
1 == "A" // 1 == NaN -> false
```

**6 & 7)** Similarly if one of the values is **boolean** then **==** prefer **numeric comparison** i.e. coerce boolean to number.

**Example -**

```javascript
Number(true) // 1
Number(false) // 0

1 == true // 1 == 1 -> true
0 == false // 0 == 0 -> true
4 == true // false
"A" == true // "A" == 1 -> NaN == 1 -> false
```

**8 & 9)** If one of the values is **object** then **==** tries to convert the object to it's **primitive form**.

You can read more about ToPrimitive [here](https://javascript.info/object-toprimitive), but to simply put it - ToPrimitive() takes two params, an object value and a hint (in case of **==** the hint is **"default"**) and tries to convert the object to **primitive**, based on the hint.

If the hint is **"default"** it takes the hint based on the other value.

If the hint is **"number"** it tries to convert the object to number using **"valueOf"** then **"toString"**.

If the hint is **"string"** it tries to convert the object to string using **"toString"** then **"valueOf"**.

**Example -**

```javascript
let a = "alok";
let b = ["alok"];
b.toString(); // 'alok' i.e. primitive

a == b; // "alok" == "alok" -> true

let c = ["alok","1"];
c.toString(); // 'alok,1' i.e. primitive

a == c; // "alok" == 'alok,1' -> false
```

Here when comparing a **string** and **object** the hint is **"string"** and it tries converting the object (**["alok"]**) to primitive and as the hint is "string" it first tries **"toString"** and gets **"alok"** which is a primitive and then the comparison is done.

**Example -**

```javascript
let a = "alok";
let c = ["alok","1"];

c.toString(); // 'alok,1' i.e. primitive

a == c; // "alok" == 'alok,1' -> false
```

**Example -**

```javascript
let a = 1;
let b = ["1"];

b.valueOf(); // [ '1' ] i.e. not primitive
b.toString() // '1' i.e. primitive

a == b; // 1 == "1" -> 1 == 1 -> true
```

Here when comparing a **number** and **object** the hint is **"number"** and it tries converting the object (**["1"]**) to primitive and as the hint is "number" it first tries **"valueOf"** and gets **[ '1' ]** which is not primitive thus it tries **"toString"** and gets **"1"** which is a primitive and then the comparison is done.

**10 )** else return **false**

---

### Wrapping Up

We just saw that == and === is not just simply loose comparison and strict comparison rather == allows coercion and === doesn't. Knowing these details will surely help you to write better code.