Hey, Mom! The Explanation.

Here's the permanent dedicated link to my first Hey, Mom! post and the explanation of the feature it contains.

Wednesday, August 14, 2019

A Sense of Doubt blog post #1639 - Best Javascript Meme - COERCION


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/


/#JAVASCRIPT

The Best JavaScript Meme I've Ever Seen, Explained in detail



Yazeed Bzadough

Yazeed Bzadough

I create content for developers who want a deep understanding of their tools.

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.
best-js-meme-to-date-2
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?
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
panel-1-1

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!
this-is-javascript

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.
scumbag-javascript

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....
that-string-secretly-became-a-number

Weird right? Well get used to it, we're not even halfway done.
Panel 2 - Arrays Get Coerced Too
panel-2

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
arrays-are-objects

Sorry to break it you.
2. Empty array becomes empty string
Again according to the spec, JS first looks for an object's toString method to coerce it.
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() // ""

empty-array-coerces-to-empty-string-1

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
empty-strings-become-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...
coercion-every-time-2


Panel 3 - Quick Recap
panel-3-1

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!
panel-4-1

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
just-use-triple-equals

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: