This is part of a series where I try to explain through each of 33 JS Concepts.
This part corresponds to the Double Equal vs Triple Equal.
That is all you need to know. No, I’m just kidding! But you do need to know that.
== is known as loose equality.
=== is known as strict equality.
What is difference between loose and strict?
Loose Equality performs Coercion.
Strict Equality does not perform Coercion.
Coercion is defined here follows the rules specified in the Abstract Equality Comparison Algorithm as defined in the ES Spec.
Case 1 - Both of the operands are of same types
Take Aways from here:
NaNis not equal to itself or anything else.
+0is equal to
-0(not that anyone uses them)
Case 2 - The operands are null and undefined
These people are very special and they are coerced to be equal to each other.
Unlike others this is something that has constant applications. There might be functions that you want others to write and take the result from. You have instructed them to return
null if the result is falsy but they forget. You have not got
null, but you have got
undefined in you hands. Instead of writing these an
|| to compare them you can compare the result with
== to get the exact result you want.
This also means that they are not equal to anything else. If you try
undefined == false, you are ought to get
false out of it.
Don’t believe me? Try it out yourself.
Case 3 - One is string and the other number
The string is being converted into a number here. If it is not a number, you will get an
NaN, which is not equal to anything else anyway (not even itself as we mentioned)
Case 4 - Boolean and something else
Huh? Where is the coercion I was promised?
Coercion is still happening, we are not just looking at it the way compiler is. If compiler sees a boolean on either side of the
==, it converts the boolean into a number and repeats the algorithm. So in our case,
true gets converted to
1 and Is
12 == 1, No; and hence
You know what would be right though?
1 == true, try it.
What if the other side is not a number? Say
"12" == true, let’s break it down:
- Compiler sees a boolean:
"12" == toNumber(true)—>
"12" == 1
- Compiler sees a string:
toNumber("12") == 1—>
12 == 1(Case 3)
Case 5 - String/Number vs an Object
Lots of things here, let’s break them down one by one.
If we find an object on either sides of the
== operator, we try converting it to a primitive.
How might we do that?
Objects have two methods defined to do this:
valueOf by default returns the object itself,
More like I’m Groot. But this time, annoying.
Rule 1: These two methods can only return primitives.
There are no errors if they return other stuff. It just ignores the value.
I mean, Common!
valueOfjust broke their only rule with it’s default value.
- Empty object is not a falsy value, no coercion here.
As we had mentioned in our Coercion article, arrays have a
toString() function defined by default.
== is a nuetral (default) case, compiler calls upon
toString() on the array. which is
join(','). What happens when we apply that function to an empty array? We get
"", which is falsy.
Let’s recount the step the steps now:
falsegets converted to number (case 4)  == 0
toStringis invoked "" == 0
- String and number (Case 3)
0 == 0 —>
The same explanation explains 3, 4, 5 cases, so we will skip those.
6 asks the important question:
What if object has both
The compiler first makes some guesses about it.
Is it someplace a string would make sense? Like say, as an object key? Then prefer
Is it somewhere a number would make sense? Like in a mathematical expression? Then
Is it someplace where both could exist? Like
This is how the last one turns out to be false.
Can I get this hint the compiler makes and take a decision on it?
With ES6 and some magic with Symbols, yes you can.
Case 6: Object vs Object
If the two objects compared are of same reference, then
This is actually same for both
===, just making the point.
Does this change the way I code?
There is a choice to be made here. Stalwarts like Douglas Crockford, recommend that you should always use
=== instead of
==. There are people like Kyle Simpson who thinks understanding
== would be a far better option.
There is an interesting conversation between Kyle Simpson and Brendan Eich on twitter about this:
also, defaulting to === could be *slightly* less performant.— getify (@getify) February 5, 2019
when the types are different, the behavioral equiv of x == y (allowing coercion) actually requires two or more === usages. one == usage is faster than two === usages.
To quote a Stackoverflow answer on the topic,
Douglas Crockford makes a lot of recommendations, but you don’t have to take them as gospel. :)
Have your opinion, have a team huddle, decide and code.
That’s about it about call stack for now. Is there something I missed? Something wrong? Something good? Ping me on Twitter