Though it can come at the cost of blatantly defying the often pretentious opinions of JSLint (I prefer JSHint), I enjoy using a lesser known bit of JavaScript: the ~ operator.

~ is the bitwise NOT operator in JavaScript. It’s a unary operator (it operates on a single operand) that flips the bits that represent the number it is operating on—this is the One’s Compliment of a number. If you’d rather think about it in terms of a mathematical formula, it will give you the result of -(N + 1).

Take the number 500. In binary it’s represented as:

500 = 00000000000000000000000111110100

(Operands of bitwise operators (such as ~) are always converted to signed 32-bit integers.)

The value is ~500 will return the one’s compliment of 500. Look closely at the two binary strings together, and you’ll see that the binary representation of -500 is simply the binary representatino of 500 with each bit flipped (1 becomes 0 and 0 becomes 1).

~500 = -501 = 11111111111111111111111000001011
 500 =        00000000000000000000000111110100

Checking for Existence

When you’re looking for element n in an array a, you usually break out .indexOf(). If the script finds n as the first element in a, then it will return zero: a falsy value. This false negative result requires the conditional to check, specifically, for a value that isn’t -1.

In other words, we can’t do this:

if (a.indexOf(n)) {}

We need to do this:

if (a.indexOf(n) !== -1) {}

Stylistically, I’m not a huge fan of how that looks. But we can use the ~ operator to cut this down a bit. Remembering that ~ equates to -(N + 1), it’s clear that substituting N for -1 will return in 0. Since 0 is a fasly value, we can shorten our conditional to:

if (~a.indexOf(n)) {}

Follow the table below to see why ~ works in this scenario:

a n found? a.indexOf(n) ~a.indexOf(n)
[‘a’, ‘b’] b found 0 -1
[‘a’, ‘b’, ‘c’, ‘d’] c found 2 -3
[‘a’, ‘b’] z not found -1 0

As seen above, if n exists in a, then ~a.indexOf(n) will be a non-zero value, and therefore truthy. This is not the case for a.indexOf(n), where it will return 0 if n is found in the first index.

Sure it might sound a little pedantic and saves a negligible amount of bytes, but this is purely about coding style and preference.

Truncating a Decimal

If you have a decimal, say 25.14, and you want to round down, a common method is to use JavaScript’s built-in Math.floor(25.14) === 25. You could even use parseInt(25.14, 10). If you’re feeling a little crazy, you could do something completely absurd like +String(25.14).split('.').shift();.

While all the above work fine (the last one works, but I wouldn’t call it “fine”), there is a more succinct way to “floor” (it’s actually truncating) a decimal. This is, of course, using the ~ operator. Two of them, to be precise.

When you use ~ on a decimal, it will convert it to an integer:

~24.15 === -25

Again, refer back to the mathematical representation of ~, -(N + 1), and consider applying two of them at once:

= ~(-(24.15 + 1)) = ~(-25)  // (remember the integer conversion from ~)
= -(-25 + 1)
= 24

As seen above, applying ~ twice has the same result of truncating a decimal. More obviously,

Math.floor(24.15) === ~~24.15 === 24

Another way to think about how ~~ ends up truncating a decimal, is to use two facts about how ~ operates:

  1. It automatically converts a decimal to an integer.
  2. It inverses the binary representation of the number.

When we use ~~, the first ~ will chop off any decimal and flip the bits (all 1s go to 0s, all 0s go to 1s). The second ~ will then flip the bits back to their original position, and therefore return the original number sans decimal.


~~24.15  // 24
~~10     // 10

(Yes, you can also use tricks like n | 0, but this post is about ~)

A Huge Caveat

While this is a neat and quick way to truncate the decimal from a number, an issue does exist—note that I’ve been saying truncate and not floor. This is because ~~ does not floor, as it is popularly believed:

Math.floor(-20.51) === ~~-20.51  // FALSE!

The actual mathematical definition of the “floor” of some variable x is the largest integer y that is not greater than x. In the case of negative numbers, simply truncating the decimal will not give you the floor!

Take -20.51 for example. Using the mathematical definition, the floor of -20.51 is the largest integer that is not greater than -20.51 itself. This would be -21, not -20, since -21 < -20.

JavaScript’s built-in Math.floor() handles this correctly, while ~~ does not:

Math.floor(-20.51) === -21
~~-20.51 === -20

In Conclusion…

~ is a neat operator that has shining moments as well as dark pitfalls. Use it with care and it will reward you, use it carelessly and you risk frustrating bugs that evade detection. It can make your code look much more sleek and pretty (hey, just my opinion), but others feel it can make the code confusing and unreadable for those not familiar with the language. It all comes down to personal preference, and more importantly, the code style guidelines for the project you’re working on. If it’s your own project and you like ~, just remember to force JSHint to share your opinion with bitwise: true!