Metal Toad has been building applications and cloud environments for some of the most well-known global brands for over a decade. Learn more > >

Javascript WAT: Diving into ECMAScript Abstract Equality Comparison Algorithm

I'm assuming most of you saw Gary Bernhardt's talk from CodeMash 2012 on some WAT™ features in Ruby and JavaScript. If not, I highly recommend you do as it's thouroughly amusing. No, seriously. Go ahead, I'll wait...

Before I say anything else, I am going to go on the record and say that I love JavaScript. It is one of my favorite programming languages. I find it therapeutic most of the time. It is a prototypal, dynamic and "weakly typed" programming language that treats functions as first class citizens. Transitioning from a class based OOP to a prototypal OOP can be a struggle at first, but as soon as you accept the simple truth that there is no spoon, you will realize that you know kung-fu.

That being said, every once in a while you will run into a JavaScript "feature" that will have you scratching your head and going:

lol, wat?!

I recently watched JSConf video by Shirmung Bielefeld on equality operators in JavaScript and I found the following conundrum in the comment section:

1. if([]) { console.log('True'); } else { console.log('False'); } // returns True :D
2. [] == false // empty list compared to false, returns true
3. [] == true // empty list compared to true, returns false

Now, the if statement makes sense. I know that all objects in JavaScript are truthy (even empty objects) and JS arrays are objects, so the if statement evaluates to true as expected. However, [] == false evaluating to true is a prime example of JS WAT™ moment. I would expect both 2. and 3. to evaluate to false, or at worst [] to resolve to its truthy value and 3. to evaluate to true and 2. to evaluate to false. However, that would make sense and would make JS gremlins unhappy and ain't nobody got time for that.

On a serious note, the answer to this lies in ECMAScript's spec for Abstract Equality Comparison Algorithm - better known as: == operator. Let's go step by step and take a look at how the JavaScript engine interprets [] == false.

7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
// [] == false becomes [] == 0
 
9. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
// Now [] is being converted to primitive by calling implementation of [[DefaultValue]] with hint of string, which is effectively calling toString on an empty array (which returns empty string or "").
// [] == 0 becomes "" == 0
 
5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
// "" == 0 becomes 0 == 0, which evaluates to true.

So it is not a gremlin, it's a "feature" after all. Now we know ECMAScript spec for == operator and we can develop some intuition to how objects will be evaluated via Abstract Equality Comparison Algorithm. Using the same logic as above, we know that {} == false will also be evaluated to true, right? Wrong! The difference is subtle and consistency is overrated. I'll leave this one for you to figure out. If you get stuck and if you are interested as to why this is, leave a comment below and I'll follow up. Or even better, share your favorite WAT™ JavaScript moment.

Consistency: It's only a virtue if you are not a screwup.

Filed under:

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready to get started?