WhatTheFish Moments of JavaScript

WhatTheFish Moments of JavaScript

Decoding JavaScript Behaviour That Makes No Sense. Starting from the Funniest and Confusing JS Meme I’ve Ever Seen.

Cover Photo by kazuend on Unsplash

JavaScript is known to have some weird/crazy moments that make you go like “WhatTheFish”. This article summarizes a few of those WTFish moments to help you get a better understanding of what happens behind the scenes.

JavaScript is an excellent programming language. It features a straightforward syntax, a big ecosystem, and, most importantly, a fantastic community.

At the same time, we are all aware that JavaScript is a really amusing language with some tricky aspects. Some of them may rapidly transform our mundane jobs into a living nightmare, while others can make us laugh out loud.

Let’s start with some laughter and madness — Memes :D

WhatTheFish moments

1) Coercion Madness

image.png

I saw this meme on a Reddit page and was like WhatTheFish is this!!! But after carefully reading it again I understood what was happening. This meme is all about the concept of coercion in JavaScript.

Coercion–Automatically changing a value from one type to another.

Let's try to understand what is going on. If you verify the above in your chrome dev console, you will find that it is surprisingly true.

I will explain this meme step by step.

Step 1

0 == "0"
// true

What is really happening here?

The string on the right is converted to a number and compared with the number on the left. Here’s the official ECMAScript Language Specification on that. We will think of it as Rule 1.

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!

Note that it is always the element on the right that undergoes conversion.

Step 2

0 == [] //true

What happens here?

An empty array is deemed to be equal to number 0.

There are three things you should know about arrays in JavaScript.

  • Arrays in JavaScript are objects. Yes, objects!!

  • In the above example, the compiler tries to coerce the array into a string.

In a normal array, this is what would happen if you use the toString() method.

image.png

Now in the above empty array, if you try the same toString() method, it would result in an empty string.

[].toString()
// ""

The concept used by the compiler is mentioned the specs as,

If x is String or Number and y is Object, return x == ToPrimitive(y)

The spec’s ToPrimitive turns this empty array into an empty string. References are here and here.

We will think of this as Rule 2.

  • An empty string is coerced to 0

Now we are back to Rule 1, where a string is converted to a number. In this case, the empty string is converted into the number 0.

toNumber("") // 0

Well, nothing is nothing right. Sometimes things don’t really make sense. But we have to accept the way it is.

Now we should be able to understand this step. To summarize this step,

image.png

Step 3

Now we are comparing,

"0" == [] //false

If you have understood the rules up to now, this should not be puzzling as before. Let's see how this unfolds.

The value on the right is coerced — i.a the empty array is coerced. As we saw in step 2, the empty array will be converted to an empty string.

[].toString() // ""

And then the empty string will be converted to the number 0 as we saw in step 2. Will it ?

toNumber("")//0

NO. You are wrong. Things are not like before!!

We are comparing "0" with [] . Not 0 with [] . The empty array will be simplified to an empty string — "". But the value on the left is still the string 0 — "0" .

As both values are strings, the JS compiler decides not to coerce anything further.

Hence the output is false as "0" != “ ”.

To summarize all these steps,

image.png

That was fun right!! It might be frustrating in the beginning, but once you understand how the whole thing works, you will feel complete.


2) Relational Operator Confusion

What do you think the output for the below code is?

console.log( 3 > 2 > 1 )

True? Nope It is false.

Explanation

The reason we assumed it would be false is that we concluded, console.log( 3 > 2) // true and console.log( 2 > 1) //true. Then console.log( 3 > 2 > 1 ) must also be true.

But what actually happens is that the JS compiler takes the value True as 1. Now let's see the process.

image.png

As you can see above, the comparison is ultimately between 1 > 1 // false which turns out to be false. Hence our output is printed.

image.png


3) Unexpected Sorting

Let's imagine you want to sort an array of numbers in ascending order. We shall use the Array.protype.sort() method.

[ 4 , 150, 20, 9].sort()

The output should be [4, 9, 150, 20] right. Well, No!!

This code will print [150, 20, 4, 9]. How is 150 lower than 20. Probably a WhatTheFish moment for you.

Explanation

What really happens is that the Array.prototype.sort() method is built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

In this case, the numbers are converted into strings and then are compared. Although 150 is the biggest number, the algorithm converts it into a string "150" and checks whether "1" > "2" //where “2” is from “20". As it is if false, the algorithm places the value 150 as the first element of the sorted array. Similarly "2" < "4" < "9" . Hence the final result,

image.png

Solution

To sort a numerical array in JavaScript, you can use the above-mentioned sort function itself. But by passing a function as a parameter. This parameter function is called the compareFunction. The code snippet to sort the above array is,

image.png

This function simply returns the difference between the two compared numbers. To get a number array sorted in descending order, you simply return b-a instead of a-b.


Although I have included 3 “WhatTheFish” moments of JavaScript, JS has a lot of surprises in store for us. You will definitely come across quite a few in your lifetime.

“I don’t think anyone ever really knows JS, not completely anyway.” — Kyle Simpson


Resources