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.
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.
Take Aways from here:
NaN
is not equal to itself or anything else.+0
is equal to -0
(not that anyone uses them)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.
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)
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 false
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:
"12" == toNumber(true)
--> "12" == 1
toNumber("12") == 1
--> 12 == 1
(Case 3)false
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.
Objects have two methods defined to do this:
toString()
valueOf()
valueOf
by default returns the object itself, toString
says [object Object]
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!
valueOf
just broke their only rule with it's default value.
As we had mentioned in our Coercion article, arrays have a toString()
function defined by default.
As ==
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:
false
gets converted to number (case 4)
[] == 0[]
toPrimitive called, toString
is invoked
"" == 0true
The same explanation explains 3, 4, 5 cases, so we will skip those.
6 asks the important question:
valueOf
and toString
?The compiler first makes some guesses about it.
Is it someplace a string would make sense? Like say, as an object key? Then prefer toString()
Is it somewhere a number would make sense? Like in a mathematical expression? Then valueOf
Is it someplace where both could exist? Like ==
? Then valueOf
anyway.
This is how the last one turns out to be false.
With ES6 and some magic with Symbols, yes you can.
If the two objects compared are of same reference, then true
otherwise false
.
This is actually same for both ==
and ===
, just making the point.
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. 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.
— getify (@getify)
February 5, 2019
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 === vs == for now. Is there something I missed? Something wrong? Something good? Ping me on Twitter