Alok Kumar

Posted on

# JS Equality in-depth

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:

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 :-

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 :-

1 === NaN // false
NaN === 1 // false

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

Example :-

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 :-

+0 === -0 // true
-0 === +0 // true

f } else returns false.

Example :-

1 === +Infinity // false
1 === -Infinity // false

3) When neither x nor y are number values then comparison is performed as follows:

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.

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 - *

"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 -

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 -

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 -

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:

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 -

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 -

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 -

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, 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 -

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 -

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

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

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

Example -

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.