JavaScript ES6 Bitwise Operators

Bitwise operators are mainly used for advanced performance tweaking in JavaScript. They are less frequently used but can make you a more sophisticated developer if you understand their benefits.

In this article, we discuss the benefits of using bitwise operators including real world use cases for each.

What are bitwise operators?

Bitwise operators act on the binary representations of their operands (or arguments). This improves performance since operations act on individual bits rather than more complex representations of values.

Bitwise operators with examples

Bitwise operators still return numeric values. Let's take a look at each binary operator with a real world application of each.

Bitwise And &

1 & 1 // returns 1 
2 & 1 // returns 0
3 & 2 // returns 2

The & operator returns a 1 for each bit position where both values are 1. Take the 3 & 2 example.

11 //the binary representation of 3
10 //the binary representation of 2
10

Since both 3 and 2 have a 1 in the same bit position, we return a 1 for the resulting position. For the other positions, we return 0. This results in 10, which is the binary representation of 2. This is why 3 & 2 returns 2.

In the real world...

You can use the & operator to easily check if a number is even or odd. For example:

(x & 1) === 0

This evaluates to true if x is an even number. The binary representation of even numbers always ends in 0. Since there is only one digit for the binary representation of 1, x & 1 will always return 0 for even numbers.

Bitwise Or |

1 | 1 // returns 1 
2 | 1 // returns 3
3 | 2 // returns 3

The | operator returns a 1 for each bit position where either value is a 1. Take the 3 | 2 example.

11 //the binary representation of 3
10 //the binary representation of 2
11

Since a 1 exists at each bit position for either 3 or 2, we get 11 (the binary representation of 3). This is why 3 | 2 returns 3.

In the real world...

You can use the | operator to easily floor positive numbers. For example:

5.23 | 0 //returns 5

Bitwise XOr ^

1 ^ 1 // returns 0 
2 ^ 1 // returns 3
3 ^ 2 // returns 1

The ^ operator returns a 1 for each bit position where one, but not the other, value is a 1. Take the 3 ^ 2 example.

11 //the binary representation of 3
10 //the binary representation of 2
01

This returns 1 because the bit position is only different for one the bits.

In the real world...

You can use the ^ operator to for swaping variables or toggling switches. For example:

a ^= b, b ^=a, a ^= b;

If you set the values of a and b then run the above example, you will notice the returned result toggles between the two variables.

Bitwise Not ~

~1 // returns -2 
~2 // returns -3
~3 // returns -4

The ~ operator simply inverts the bits! All 1s become 0 and all 0s become 1. It's important to remember that JavaScript uses 32 bit operands. Also, the first 0 in the 32 bit representation indicates either positive or negative.

~2
00000000000000000000000000000010 //the 32-bit binary representation of 2
11111111111111111111111111111101 //inverts all the bits, returning -3

In the real world...

The ~ operator can be used to perform Array includes. For example:

!!~arr.indexOf(x)

The indexOf() method returns the position of the argument x in the array. If x is not included in the array, -1 is returned.

Since ~(-1) == 0 and !!0 == false, we return false if x isn't in the array.

Bitwise Shift Operators

Zero fill left shift <<

The << operator takes a 32 bit signed integer and pushes 0's in from the right while left-most bits fall off.

Signed right shift >>

The >> operator takes the left-most bit of a 32-bit integer and pushes copies of it from the left. Values from the right fall off but the left-most bit remains the same.

Zero fill right shift <<<

The <<< ignores the signage and pushes 0 s from the left regardless of left-most bit value.

In the real world...

Shift operators can provide alternatives to arithmetic operators. For example:

x << 2 // always returns x * 4

Conclusion

Some of these examples may leave you asking, "but why?". While modern libraries and frameworks have largely eliminate the need to use these operators directly, they still deserve a place in your arsenal. Use bitwise operators to increase performance when performance matters most.

Your thoughts?