JavaScript: Equality comparison with ==, === and Object.is

Subscribe to my newsletter and never miss my upcoming articles

#100DaysOfCode is a great engagement to refresh some of the concepts that are basic, but extremely important. Today, I spent time on refreshing my memory on JavaScript's equality operators and methods. Thought, why not to write about it?

Traditionally JavaScript provides 2 special operators for equality comparison:

  • == for Abstract Equality Comparison which performs a loose equality between the operands.
  • === for Strict Equality Comparison which performs a strict equality between the operands.

With ES6, we have one more way to perform the Same-value equality using Object.is method. In this article, we will get deeper in understanding the usage, impact and use-cases of all of them.

Abstract Equality Comparison with ==

Abstract equality comparison(aka, loose equality comparison) compares two values for equality, after converting both the values into a common type. In this type of comparison, type coercion is performed by JavaScript.

Type coercion is the automatic or implicit conversion of values from one data type to another (such as strings to numbers).

Let us understand this with an example. Consider two different animals from the type Rodent, i.e, hamsters and guinea pigs. I have no doubts that, the equality comparison with == is going to return true by coercing their type to rodent.

image.png

In programming,

true == 1 // true
'0' == 0 // true
[9, 2] == '9,2' // true
"" == 0 // true

You would find the == operator strange, if you are new to the JavaScript and holding your experiences of value comparisons from another programming language.

That's not all. The == operator also has an evil sister called, !=. It does just the opposite comparison of two values to check if they are not equal. However, just like ==, it also does a type conversion which leads to confusions.

Strict Equality Comparison ===

With strict equality comparison, guinea pigs and hamsters are not equal as, === compares two values for equality. Neither of the values are implicitly converted(coerced) to some other value before being compared.

With Strict Equality Comparison, If the values have different types, the values are considered unequal.

true === 1 // false
'0' === 0 // false
[9, 2] === '9,2' // false
"" === 0 // false

The === also has an angel sister called, !== which helps in finding if two values are strictly not equal. We should be using the strict type(=== and !==) comparison over the loose type(== and !=) comparison almost always.

But why almost? Why not always?

The === handles NaN, -0, and +0 bit differently.

NaN === NaN // false
+0 === -0 // true

Strict equality treats NaN as unequal to every other value, including itself. It also doesn't care about the difference between +0 and -0. Now for some situations, these differences may matter and the strict equality may fail there.

Same Value Equality with Object.is

With ES6, we have a new way to determine if the two values are same.

Object.is(0, 0) // true
Object.is(null, null) // true
Object.is(undefined, undefined) // true
Object.is(true, 1) // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

From MDN:

Two values are the same if one of the following holds:

  • both undefined
  • both null
    • both true or both false
    • both strings of the same length with the same characters in the same order
    • both the same object (means both object have same reference)
    • both numbers and
    • both +0
    • both -0
    • both NaN
    • or both non-zero and both not NaN and both have the same value

Quiz Time

Let us try answering couple of questions based on the concepts we have learned so far,

Why do you think, the output is false in all the cases?

let obj1 = {name: 'GreenRoots'};
let obj2 = {name: 'GreenRoots'};

obj1 == obj2 // false
obj1 === obj2 // false
Object.is(obj1, obj2); //false

It is because, JavaScript has five primitive data types that are passed by value: Boolean, String, Number, null, and undefined.

Rest of the data types are called non-primitives and those are mostly Objects(yes, including Array, Function and Object itself). These non-primitives types are passed by reference.

Hence both obj1 and obj2 above holds the value as the different memory locations that they are created on. Hence the comparison will be false always.

Here is an article that shows the Object reference concepts visual way,

Do you think the Object.is comparison result really matters over ===?

Yes it does. React uses Object.is algorithm to compare the state. Find a great explanation of it in this article by Avinash Ega.

Comparison chart

Here is a comparison chart with sample values compared using, ==, === and Object.is:

image.png


If it was useful to you, please Like/Share so that, it reaches others as well. To get e-mail notification on my latest posts, please subscribe to my blog by hitting the Subscribe button at the top of the page. You can also follow me on twitter @tapasadhikary.

The cartoon in the cover image is from pngguru.

Pankaj Patel's photo

Thanks for a nice refresher on equality checks in JS

The Table for quick results on equality is pretty cool.

Victoria Lo's photo

Nice refresher for me too. Love it!