Demystifying "==" and "==="

Demystifying "==" and "==="

ยท

7 min read

One of the most common interview question that every Javascript developer has encountered in their career is "What is the difference between == and ===". Well, I guess most of them reading this would already have come up with the most common answer which is

''=='' compares value and "===" compares both value and type.

What if I say that this isn't the right answer ๐Ÿ™ˆ. Let's dive deep and understand what's happening behind the scenes. According to the ECMA Script specifications, both == and === checks the type of the variables. If the types are same, both == and === work exactly the same post which they return true or false based on the values. It's when the types of the variables are not matching, both differ. ๐Ÿ˜ณ

When the types are not same, == does an implicit coercion while === directly returns false. Implicit Coercion is nothing but the conversion of variable from one type to another.

Based on the ECMAScript specification, whenever Javascript encounters a == operator, an abstract operation called IsLooselyEqual ( x, y ) gets invoked. Similarly, when it encounters a === operator an abstract operation called IsStrictlyEqual ( x, y ) gets executed. I understand this might be too much to digest at the moment but lets try to understand both these operations with the help of some code snippets. We won't be covering all the cases of the operation, rather we would try to address some of the common scenarios that we encounter normally.

Screenshot 2021-09-05 at 1.45.38 PM.png

Screenshot 2021-09-05 at 1.45.54 PM.png

Case 1:

var stringOne = '1';
var numberOne = 1;

if (stringOne == numberOne) {
  console.log("IsLooselyEqual(x,y) is invoked");
}

In the above code snippet, we have two variables -stringOne and numberOne of types string and number respectively. After which we have a conditional statement where we check if stringOne and numberOne are equal using the == operator. As soon as the Javascript encounters == operator it applies the IsLooselyEqual(x,y) abstract operation. According to this operation, following steps are done.

  1. It checks if the types of stringOne and numberOne are same or not. If they are same, it returns a value by applying IsStrictlyEqual(x, y) (Step 2 of the actual algorithm) abstract operation where x would be stringOne and y would be numberOne respectively.

  2. If the types are not same, it checks if the type of stringOne is a String type and type of numberOne is a Number type (Step 6 of the actual algorithm) . Since it's true, it converts stringOne variable into a Number type by applying the ToNumber(x) abstract operation. ToNumber(x) is another abstract operation which converts the variable to a Number Type variable. In this scenario, stringOne would be x, applying ToNumber(x) operation would be ToNumber(stringOne) where stringOne would be converted from String type to Number type based on this . After which it returns the value by applying IsLooselyEqual(x, y) abstract operation again where now both x and y are of the same type.

  3. Since both are of the same type, it returns the value by applying IsStrictlyEqual(x,y) abstract operation.

  4. IsStrictlyEqual(x,y) checks if the types of both x and y are the same. If the types are same, it checks the value of both x and y. If the values are also the same, then the operation would return a true else it would return a false.

Case 2:

var arrayOne = ['1'];
var numberOne = 1;

if (arrayOne == numberOne) {
  console.log("IsLooselyEqual(x,y) is invoked");
}

In the above code snippet, we have two variables arrayOne and numberOne of types object and number respectively. After which we have a conditional statement where we check if arrayOne and numberOne are equal using the == operator. As soon as the Javascript encounters == operator, it applies the IsLooselyEqual(x,y) abstract operation. According to this operation, following steps are done.

  1. It checks if the types of arrayOne and numberOne are the same or not. If they are the same, it returns the value by applying IsStrictlyEqual(x, y) abstract operation where x would be arrayOne and y would be numberOne respectively.

  2. If the types are not the same, it checks if the type of arrayOne is an Object type and type of numberOne is a String, Number etc type (Step 12 of the actual algorithm) . Since it's true, it converts the Object type variable into a Primitive type by applying the ToPrimitive() abstract operation. This operation, in brief, tries to convert the Object type to a Primitive type which would be either a String or a Number type (ToPrimitive).

  3. It then returns the value by applying IsLooselyEqual(x, y) operation by passing x and y and repeats the same steps till the types of both x and y are equal or when IsLooselyEqual(x, y) operation returns false.

  4. For the above code snippet below is the explanation on why it prints the console statement

var arrayOne = ['1'];
var numberOne = 1;

/*
  1. it checks if typeof arrayOne equals typeof numberOne

  2. if they are not the same it applies the ToPrimitive abstract operation on 'arrayOne' 
  as it's type is an Object.

  3. On applying the above operation, it becomes a primitive type which is a `String` 
  type in this case. Applying the String() to any array object will strip the '[' and ']' and 
  return the elements as a string value. In this case String(['1']) = '1'. This is what 
  happens on applying `ToPrimitive` operation.

  4. After the above step, it applies 'IsLooselyEqual(x,y)' operation again and repeats the 
  steps.

  6. Since now the `arrayOne` is of `String` type and `numberOne` is of
  `Number` type, it applies the `ToNumber` abstract operation on `arrayOne` and 
  returns the value by applying `IsLooselyType(x,y)` operation.

  7. As the types are the same, it will return the value by applying `IsStrictlyEqual(x,y)` 
  which will return `true` and hence prints the console statement present inside the 
  block.
*/


if (arrayTypeOne == numberTypeOne) {
  console.log("IsLooselyEqual(x,y) is invoked");
}

Case 3:

var objectOne = [];
var booleanOne = true;

if(objectOne) {
  console.log("This check whether array is empty or not won't work !!")
}

In the above code snippet, we have two variables objectOne and booleanOne of types object and boolean respectively. After which, we have a conditional statement where we check if objectOne is true. As soon as Javascript encounters this, it applies a new abstract operation called ToBoolean(x). This operation converts the variable to a Boolean type depending on the reference table as shown below (ToBoolean) .

Screenshot 2021-09-05 at 12.58.31 PM.png

Based on this table, since our variable is of type Object it would return us true irrespective of whether the array is empty or not. This is the main reason why we need other parameters while comparing Object types. In our case, since we clearly know its an array object, we could use the length property. Now we can refactor the above code in the following way for checking emptiness.

if(objectOne.length) {
 console.log("You won't see me since I am empty !!")
} else {
 console.log("You saw me since I am empty !!")
}

By now I hope you understood how Javascript treats the == and === operator and cases when they are actually different. Above mentioned were just few scenarios out of many. If you are really interested to dig deeper, I would recommend you to go through ECMA Specifications where you will find the complete implementation of both IsLooselyEqual(x,y) and IsStrictlyEqual(x,y) abstract operations. I would also encourage you to read this book if you haven't - You Don't Know JS by Kyle Simpson.

Thank you

Hope you enjoyed this read on == and === operators and how comparisons works in Javascript. Now you can make use of this knowledge to really ace the above question in your upcoming interviews ๐Ÿ˜œ. Let me know your thoughts in the comment section down below. If you feel this article is useful, please do show your love and share this to your fellow beings who could make maximum use of this. Always feel free to connect with me via twitter, linkedIn or email. Happy to help in all ways possible ๐Ÿ˜Š

Until we meet again, The Mallu Dev signing off ๐Ÿ‘‹ Cheers ๐Ÿฅ‚