DEV Community

Saloni Yadav
Saloni Yadav

Posted on • Edited on

Little shenanigans of JavaScript

Even after working with JavaScript for over three years now, it never fails to surprise me with its little tricks and sly outputs. But these very secrets and surprises makes me fall in love with this language, all over again. Everytime!🤩

Some people don't find these shenanigans hindering their practical work. But believe me, I avoided a production bug (which would have made my fancy looking UI go berserk) by serendipitously testing a sample dataset that unveiled yet another sly trick of JS arithmetic.

And so, finally, I decided to compile a few such tricks here in this post. Hope you have fun discovering something new.

1. Adding float numbers

console.log(0.1 + 0.2)
console.log(0.1 + 0.2 - 0.2)
console.log(0.1 + 0.7)
console.log(0.2 + 0.7)
Enter fullscreen mode Exit fullscreen mode

Run the above code in your developer console and be like WTF!! How can you mess up something as simple as this JS??

If you are too lazy to check for yourself, this is what the output looks like:

0.30000000000000004
0.10000000000000003
0.7999999999999999
0.8999999999999999
Enter fullscreen mode Exit fullscreen mode

The reason behind this behavior is the accuracy with which JS stores float values.

I was working on a report visualization project where I had to display the total bounced email percentage by adding up soft-bounce and hard-bounce. Since this was to be displayed in a compact UI, displaying 0.30000000000000004% instead of 0.3% would make my page go insane (much to the amusement of the user). Fortunately, I realised it as soon as I tested it and fixed it.

So, how do we fix this?

let a = +(0.1 + 0.2).toFixed(1)
let b = +(0.1 + 0.7).toFixed(2)
Enter fullscreen mode Exit fullscreen mode

Explanation:
toFixed(num) converts the float to string with precision of num after decimal point. The unary operator converts the string back to number. If you are using this to display somewhere in your UI, you are pretty much done after 'toFixed'. If you are going to use it for further calculations, go ahead and convert it to number.

But note:
"0.30" in string when converted to number becomes 0.3. So, don't be surprised.

2. Silent conversions

I don't see why someone would write a code like this, but let's assume you somehow landed with these set of numbers (say from an API call response) and are performing an operation as below:

console.log(022 === 018) //true
console.log(023 === 019) //true
console.log(010 === 008) //true
//if i keep going on, you will soon see the pattern
Enter fullscreen mode Exit fullscreen mode

Common, don't be lazy and give this a shot in your console. The best way to learn JS is to befriend that F12 of your browser.
Most of you would have guessed what's happening here. But let me lay it down for you either way...
When JS sees 0 in the start of a number, it converts it to Octa. That explains 022, 023, 010 (you can experiment more). But wait! 8 and 9 are not valid numbers of the Octa Number System. Well, that's why they are converted to Decimal.
And this explains 022 (18 in Decimal) even strictly matches with 018.

3. Let's get Quirk-ier

There is no real-world example of this crazy expression, but I loved it so much that I decided to pop it in anyways. I came across this in WTF-JS (quite apt!).

console.log((!+[]+[]+![]).length)
// 9
Enter fullscreen mode Exit fullscreen mode

Yes, the answer is 9! Whaaaaa 🤐
There was no way I was going to give up without finding out why! After a gazillion unsatisfying hypothesis, I finally made one that I am quite sure of, and here it is...

But before scrolling down for the solution, I urge you to try figuring out for yourself. Believe me, it's Merlin's Beard Satisfying!

Explanation:
First let's see what are we finding the length of, at first place?

console.log(!+[]+[]+![])
// Ans: "truefalse"
//HOLY CHRIST!!!!
Enter fullscreen mode Exit fullscreen mode

How on earth did JS do this??
Let's chop it down to three parts:
(!+[]) + ([]) + (![])

  1. ! alone is really nothing in JS. God knows why it took me so long to figure out... And soooo,
    +[] works as a unary operator on an empty object, which basically converts [] into Number.
    Since [] is an empty array, its numeric value is 0.
    So this is equivalent to !0 == true (because Boolean of 0 is TRUE).

  2. [] is an empty array. Adding this with a boolean true converts both of them to string. So the stringified value of [] is an empty string "". Hence, so far we have "true".

  3. Now, the last one might be get a little tricky considering the first one in picture and if you are not aware of falsy values in JS.

Here, ![] is not the same as !0.
This time [] is NOT converted to number, but directly applied to Boolean(![]) which is FALSE.
There are only 8 falsy values in JS, find them here.

So all-in-all, this expression is equivalent to:

"true"+false
//"truefalse"
Enter fullscreen mode Exit fullscreen mode

We know here on. string + boolean = string. So the result is "truefalse". And the length of it is 9.

DAMN! This felt GOOD! 🤸‍♂️

I will end the list for now. But I have way too many such examples. If you liked it, let me know and I will make this into a series. Also, if you have such examples which got you like- Whaaaaaa 👀 , do share it in comment section.

Top comments (10)

Collapse
 
mishsom profile image
Soumitra Mishra

This is exactly why people would hate javascript, for one most developer would see !+[]+[]+![] as something that accidentally got printed by oozing off on the keyboard. :P

Collapse
 
salyadav profile image
Saloni Yadav

Hahahaha. I have to agree! But... these are the little surprises that keeps me hooked on to JS. Although this is something you will hardly ever see in a real life code base. I can’t help but enjoy these playfulness of js!

Collapse
 
kousiksatish profile image
kousiksatish

Well written!

Collapse
 
thisdotmedia_staff profile image
This Dot Media

Love these! Great compilation Saloni

Collapse
 
ayaanraj profile image
ayaanraj

really enjoyed it and learned about unary operator, and the Silent conversions is awesome.

Collapse
 
_insensible_ profile image
Mirwing Rosales

Good article, this remind me this video that I rewatch every time when I read something about how "weird" is JS

Collapse
 
jethrojm profile image
Jethro Moller (He/Him)

Interesting, thank you 😊

Collapse
 
vijayprasanna13 profile image
Vijay Prasanna

Good list!
The floating-point arithmetic is not inherently a JS issue though, more to do with the way computers handle round-offs.
0.30000000000000004.com/

Collapse
 
salyadav profile image
Saloni Yadav

Hi Vijay, thank you for pointing out. :D

Collapse
 
eldritchdev profile image
Javier Gutiérrez

Hi there! Very interesting article. Just a little correction: Boolean of 0 is false.