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)
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
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)
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
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
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!!!!
How on earth did JS do this??
Let's chop it down to three parts:
(!+[]) + ([]) + (![])
!
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 is0
.
So this is equivalent to!0
==true
(because Boolean of 0 is TRUE).[]
is an empty array. Adding this with a booleantrue
converts both of them to string. So the stringified value of[]
is an empty string""
. Hence, so far we have"true"
.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"
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)
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. :PHahahaha. 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!
Well written!
Love these! Great compilation Saloni
really enjoyed it and learned about unary operator, and the Silent conversions is awesome.
Good article, this remind me this video that I rewatch every time when I read something about how "weird" is JS
Interesting, thank you 😊
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/
Hi Vijay, thank you for pointing out. :D
Hi there! Very interesting article. Just a little correction: Boolean of 0 is false.