What is the Tilde (~) or Bitwise Not Operator in JavaScript?

JavaScript is one of the most popular languages in the world. Despite its relative ease of learning, it has some operators which may be hard for understanding. One of such operators is ~ (tilde) which means BITWISE NOT in terms of Boolean algebra.

How Does It Work?

The BITWISE NOT operator performs the NOT operation on each bit of a number it is applied to. In JavaScript, two’s complement representation is used for signed integers. For example, ~12 transforms to -13 as follows:

Base 10 Base 2
12 00000000 00000000 00000000 00001100
~12 = -13 11111111 11111111 11111111 11110011

As you may see in the table, every bit is inverted, including the highest one representing the sign of the number. Arithmetically, it is equal to the following transformation:

~x = -(x+1)

In addition, let’s see what the tilde operator does while applied to different numbers:

console.log(~-2) // 1
console.log(~-1) // 0
console.log(~0) // -1
console.log(~1) // -2

~-1 === 0: Applications

Since ~-1 is equal to 0, the tilde operator is widely used to check whether a string contains a substring.

To begin with, let’s take a look on the following code:

if ('string'.indexOf('s') >= 0) {
    console.log('Found')
} else {
    console.log('Not Found')
}

Since String.prototype.indexOf function returns -1 when a substring has not been found, the code can be rewritten as follows:

if (~'string'.indexOf('s')) {
    console.log('Found')
} else {
    console.log('Not Found')
}

When such a construction is pretty common, modern JavaScript offers more relevant functions for accurate boolean checks within arrays and strings respectively: Array.prototype.includes, String.prototype.includes. As a result, the check can be done in a more understandable way:

// string
if ('string'.includes('s')) {
    console.log('Found')
} else {
    console.log('Not Found')
}

// array
if (['a', 'b', 'c'].includes('a')) {
    console.log('Found')
} else {
    console.log('Not Found')
}

Personally, I would prefer to use Array.prototype.includes instead of ~Array.prototype.indexOf but not all browsers support the former. Unfortunately, the latter is more tricky so those who want to seem a true hacker would use it. To conclude, the good old Array.prototype.indexOf() >= 0 check is not that bad because every developer can understand it without any special knowledge.

Convert Strings and Other Values to Integer Numbers

Obviously, bitwise operators imply numbers as their arguments, so JavaScript interpreter will transform a string to a number when it finds the tilde operator. Moreover, as you might have noticed, the BITWISE NOT operator will give the same result if applied twice to a number (it is idempotent if applied twice). Consequently, the following code must be self-explanatory:

console.log(typeof '3') // string
console.log(typeof ~~'3') // number

console.log(~~'-1') // -1
console.log(~~'0') // 0
console.log(~~'1') // 1

console.log(~~-1) // -1
console.log(~~0) // 0
console.log(~~1) // 1

console.log(~~true) // 1
console.log(~~false) // 0

It is also worth noting that the tilde operator can be used for transforming floating point numbers to integer numbers because bitwise operations imply integer only operands, so JavaScript uses only the integer part of a number before inverting it:

console.log(~~-1.1) // -1
console.log(~~0.1) // 0
console.log(~~1.7) // 1

Conclusion

While getting integer parts of numbers and transforming strings/booleans to numbers can be done using other methods, the above-mentioned tricks are used in real projects so it is better to understand how they work, but I personally would not recommend to use them for writing human-readable code because they are definitely too tricky for those who are not familiar with such ‘hacks’.

In other words, the more straightforward code we write, the more people will like us.

Cheers!