It might be good to point reader to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#loose_equality_using. The rules for comparing two values of different types with == are fairly complex. It looks like [] doesn't actually go straight to 0. It looks like the standard converts it to am empty string first. At that point the types still don't match so it converts the Boolean to a Number and finishes by converting the String to a Number. The fact that the logic for what is going on is so convoluted is just another reason to not use ==.
What confused me most about this is that ![] actually evaluates to false. I had to chase that down a bit. My first thought was that this was the fault of the ! operator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT), but that just converts truthy to false and falsy to true. My confusion is because I was thinking [] was falsy. In JavaScript it isn't (https://developer.mozilla.org/en-US/docs/Glossary/Falsy). In other languages, like Python, it is.
Personally, I see all of these types of things as reasons to avoid dynamically typed languages. Don't write JavaScript, write in a better language with more logical rules that compiles to JavaScript. My personal preference is Scala.js.
Thanks for writing an article that made me think and go look up some stuff this morning.