How ~~ a.k.a double bitwise NOT operator in JavaScript can help boost performance of your app
tl;dr;
~~
casts NaN
, undefined
, null
, false
, []
, {}
, “”
and other falsey values to 0
. It can also replace Math.floor()
with ~~5.5 // 5
. Rumor has it ~~
is faster than Math.floor()
in some browsers.
Warning: ~~ will not work as a replacement of Math.floor()
on an integer greater than 2147483647
or less than -2147483648
(max value for signed 32 bit integer).
!tl;dr;
~~
comes very handy when there is a need to increment something that can be undefined
.
Let’s say we want to build a frequency table that shows how many times numbers appears in an array:
During the very first iteration n = 1
, and such key “1”
doesn’t exist in map
yet, so its value is undefined
. Thus, undefined + 1 // NaN
. The same is happening during the second iteration, and then during the third: NaN + 1
is also NaN
. So, resulting frequency table will look like:
To fix that, we would need to check for the value in map[n]
.
This is a one liner, but can we do better? Yes, with ~~
!
Some naive tests with the average value of 10 runs on node v10.13.0
Math.floor(): 3.390ms
~~: 1.458ms
WOW! That’s more than 2x performance improvement!
Strict equality check (something === undefined): 0.994ms
~~: 0.866ms
and roughly 10% improvement here.
So, not only ~~
helps to write more concise code but also improves performance.
Let’s discuss here or tweet @kutyepov
As mentioned in the very beginning of the post, ~~
cannot be used with an integer greater than 2147483647
or less than -2147483648
. This is due to fact that JavaScript is using 64 bits for number type and converts it to 32 bit to perform bitwise operations. I will go into detail on how bitwise operators work in on my next posts. Stay tuned.