JavaScript Says WAT!

Enough making fun of languages that suck. Let’s talk about JavaScript.

Gary Bernhardt

A popular pastime among programmers is to make fun of programming languages, or at least the one you choose not to use. For example, Gary Bernhardt’s 5-minute talk WAT is all about unexpected behavior, mostly in Javascript.

From www.destroyallsoftware.com

A brief summary of the video:

On January 12, 2012, at the CodeMash conference in a Sandusky, Ohio indoor water park, Gary Bernhardt presented a lightning talk titled WAT.
Bernhardt displayed some absurd anomalies in Ruby and JavaScript. After each example, he showed a funny picture that was captioned with “WAT”. The crowd loved it. It is a classic bit. Wat has become The Aristocrats of JavaScript.

But seriously though, JavaScript?!, what’s up with this:

[] + [] = ''
[] + {} = '[object Object]'
{} + [] = 0
{} + {} = NaN
Array(16).join('wat' - 1) + ' Batman' = 'NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman'

JavaScript does it differently, and this doesn’t mean it’s wrong:

Many of the jokes are due to the type coercion algorithms behind JavaScript’s “==” (equal sign equal sign) and “+” (plus sign) operators. The type coercion rules are complex, unmemorable, and in some cases, as you will see, wrong. That is why it is not recommend to use of “==” (equal sign equal sign). It implements ECMAScript’s Abstract Equality Comparison Algorithm. It is a can of worms that is not worth opening. it is better to use “===” (equal sign equal sign equal sign) instead. Some people do not like “===” (equal sign equal sign equal sign) because it looks 50% stupider than “==” (equal sign equal sign) which is itself twice as stupid as “=” (equal sign). Nevertheless, the correct equality operator in JavaScript is “===” (equal sign equal sign equal sign).

"" == false // true 
[] == false // true 
null == false // false 
undefined == false // false

The empty string is a falsy value, so a sloppy equals operator might want to conflate it with false. An empty array is not falsy, yet it also compares to false. And null and undefined are falsy values, but neither compares to false.

[] == [] // false 
[] == ![] // true

Two empty arrays are not the same object, so they are not equal. But the second line is surprising. It appears that JavaScript is a language in which x and not x can be equal to each other, which would be a seriously laughable incompetence. This is what is happening:

An empty array is truthy, so ![] is false. The sloppy equals operator wants to compare [] and false as numbers even though neither is a number. The empty array is coerced to empty string which is coerced to zero. And false is also coerced to zero. Zero equals zero, so the answer is true.

If you want to know more about equality in JavaScript, I highly recommend giving the JavaScript-Equality-Table a look.

[] + [] // "" 
[] + {} // "[object Object]" 
{} + {} // "[object Object][object Object]"

All of these cases should produce NaN. This is what NaN is for. Instead, because the values are not numbers, “+” (plus sign) wants to concatenate them. First it has to coerce them to strings. The Array.prototype.toString() method converts an empty array to an empty string. It would be better if it acted like JSON.stringify() and returned “[]”. The worthless Object.prototype.toString() method renders the objects as “[object Object]”. Then those strings get concatenated together.

I know this is not bad code as such, but it does not provide the expected result, thus you may see something that looks extraordinarily complicated – a usual sign of bad code – which is necessary because the simple version does not work.

If you want a more in-depth explanation of each WAT in this presentation, check out this stackoverflow response.

Why is JavaScript so often the butt of the joke?

Part of the reason is that it is a language that beginners pick up and never quite mange to learn – so they end up churning out some very bad code. It is also the case that JavaScript looks like a trivial language; this means you can get a long way without having to learn anything new so, again, the result is bad code. Many programmers think that when they see bad code in a language, then it is the language’s fault. Of course, you can see bad code in many languages. But JavaScript has a reputation for it that goes well beyond what seems reasonable.

In conclusion

This isn’t to say that all languages are equal, there are better and worse, of course. But too often I hear people ranting about a language being stupid for some decision, without bothering to find out why it was done that way, and what benefit they might get from it.
To which, I say: WAT!?

Further Reading

  1. https://medium.com/dailyjs/the-why-behind-the-wat-an-explanation-of-javascripts-weird-type-system-83b92879a8db
  2. https://stackoverflow.com/questions/9021109/what-is-in-javascript/9021351#9021351
  3. https://blog.caplin.com/2012/01/27/the-why-of-wat/
  4. https://missingtoken.net/ruby/2014/11/13/the-why-of-wat-ruby-edition/
  5. https://project-awesome.org/JanVanRyswyck/awesome-talks
  6. https://github.com/denysdovhan/wtfjs