DEV Community

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

Strict Equality Comparison

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Example :-

+0 === -0 // true
-0 === +0 // true
Enter fullscreen mode Exit fullscreen mode

f } else returns false.

Example :-

1 === +Infinity // false
1 === -Infinity // false
Enter fullscreen mode Exit fullscreen mode

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

Same Value Non Number

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Oldest comments (0)