A Sense of Doubt blog post #1639 - Best Javascript Meme - COERCION
Lots of posts about programming late because , you know, studying, learning, always.
Just sharing today (and a day late) as there's a lot going on.
I really liked this post that came through emails I get from Free Code Camp.
https://www.freecodecamp.org/news/explaining-the-best-javascript-meme-i-have-ever-seen/
The Best JavaScript Meme I've Ever Seen, Explained in detail
TLDR: Coerce yourself
to use triple equals.
I unintentionally
found this JavaScript meme on Reddit, and it's the best one I've ever seen.
You can verify this
meme's accuracy by running each code snippet in Developer Tools. The result
isn't surprising, but still kind of disappointing.
Of course this little
experiment lead me to wonder...
Why Does This Happen?
With experience, I've
learned to embrace JavaScript's smooth sides while bewaring its prickly pines.
Nonetheless, this corner case's details still nicked me.
It's just as Kyle
Simpson says...
"I don’t think anyone ever really knows JS, not completely
anyway."
When these cases pop up, it's best to consult the
source–the official ECMAScript
specification that JavaScript is built from.
With the spec in hand,
let's deeply understand what's going on here.
Panel 1 - Introducing
Coercion
If you run 0 == "0" in your developer console, why does it return true?
0 is a number,
and "0" is a string, they should never be the same!
Most programming languages respect that. 0 == "0" in Java, for example, returns this:
error:
incomparable types: int and String
This makes perfect
sense. If you want to compare an int and String in Java, you must first convert
them to the same type.
But this is
JavaScript, y'all!
When you compare two values via ==, one of the values may undergo coercion.
Coercion–Automatically changing a
value from one type to another.
Automatically is the key word here. Instead of
you explicitly converting
your types, JavaScript does it for you behind the scenes.
This is convenient if
you're purposely exploiting it, but potentially harmful if you're unaware of
its implications.
Here's the official ECMAScript Language
Specification on that. I'll paraphrase the relevant part:
If x is Number and y is String, return x == ToNumber(y)
So for our case of 0 == "0":
Since 0 is Number and "0" is String, return 0 ==
ToNumber("0")
Our string "0" has been secretly converted to 0, and now we have a match!
0 == "0" // true
// The second 0 became a
number!
// so 0 equals 0 is true....
Weird right? Well get
used to it, we're not even halfway done.
Panel 2 - Arrays Get
Coerced Too
This nonsense isn't
limited to primitives like strings, numbers, or booleans. Here's our next
comparison:
0 == [] // true
// What happened...?
Coercion again! I'll
paraphrase the spec's relevant part:
If x is String or Number and y is Object, return x ==
ToPrimitive(y)
Three things here:
1. Yes, arrays are
objects
Sorry to break it you.
2. Empty array becomes
empty string
In the case of arrays, toString joins
all of its elements and returns them as a string.
[1, 2, 3].toString() // "1,2,3"
['hello', 'world'].toString() // "hello,world"
Since our array's
empty, we have nothing to join! Therefore...
[].toString() // ""
The spec's ToPrimitive turns
this empty array into an empty string. References are here and here for your
convenience (or confusion).
3. Empty string then
becomes 0
You can't make this stuff up. Now that we've coerced the array
to "", we're back to the first algorithm...
If x is Number and y is String, return x == ToNumber(y)
So for 0 == ""
Since 0 is Number and "" is String, return 0 ==
ToNumber("")
ToNumber("") returns 0.
Therefore, 0 == 0 once
again...
Panel 3 - Quick Recap
This is true
0 == "0" // true
Because coercion turns this into 0 == ToNumber("0").
This is true
0 == [] // true
Because coercion runs
twice:
1.
ToPrimitive([]) gives empty
string
2.
Then ToNumber("") gives 0.
So then tell
me...according to the above rules, what should this return?
"0" == []
Panel 4 - FALSE!
FALSE! Correct.
This part makes sense
if you understood the rules.
Here's our comparison:
"0" == [] // false
Referencing the spec
once again:
If x is String or Number and y is Object, return x ==
ToPrimitive(y)
That means...
Since "0" is String and [] is Object, return x ==
ToPrimitive([])
ToPrimitive([]) returns empty string. The comparison has now become
"0" == ""
"0" and "" are both strings, so JavaScript says no more coercion needed. This is why we get false.
Conclusion
Use triple equals and
sleep soundly at night.
0 === "0" // false
0 === [] // false
"0" === [] // false
It avoids coercion
entirely, so I guess it's more efficient too!
But the performance
increase is almost meaningless. The real win is the increased confidence you'll
have in your code, making that extra keystroke totally worth it.
Thanks for reading
For more content like this, check out https://yazeedb.com. And please let me know what else
you'd like to see! My DMs are open on Twitter.
Until next time!
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- Bloggery committed by chris tower - 1908.14 - 10:10
- Days ago = 1502 days ago
- New note - On 1807.06, I ceased daily transmission of my Hey Mom feature after three years of daily conversations. I plan to continue Hey Mom posts at least twice per week but will continue to post the days since ("Days Ago") count on my blog each day. The blog entry numbering in the title has changed to reflect total Sense of Doubt posts since I began the blog on 0705.04, which include Hey Mom posts, Daily Bowie posts, and Sense of Doubt posts. Hey Mom posts will still be numbered sequentially. New Hey Mom posts will use the same format as all the other Hey Mom posts; all other posts will feature this format seen here.
No comments:
Post a Comment