JavaScript has seven bitwise operators. The term bitwise here means to operate on binary numbers. These operators are rarely utilized but are useful to know about nonetheless:
- Bitwise unsigned right-shift operator: >>>
- Bitwise left-shift operator: <<
- Bitwise right-shift operator: >>
- Bitwise OR: |
- Bitwise AND: &
- Bitwise XOR: ^
- Bitwise NOT: ~ (a unary operator)
All bitwise operators in JavaScript will first coerce their operands (or a singular operand, in the case of bitwise NOT ~) to a 32-bit integer representation. This means that, internally, a number such as 250 would be manifested as follows:
00000000 00000000 00000000 11111010
The last eight bits, in this case of 250, contain all of the information regarding the number:
1 1 1 1 1 0 1 0
+ + + + + + + +
| | | | | | | +---> 0 * 001 = 000
| | | | | | +-----> 1 * 002 = 002
| | | | | +-------> 0 * 004 = 000
| | | | +---------> 1 * 008 = 008
| | | +-----------> 1 * 016 = 016
| | +-------------> 1 * 032 = 032
| +---------------> 1 * 064 = 064
+-----------------> 1 * 128 = 128
=================================
SUM = 250
Adding together all of the bits will get us a decimal integer value of 250.
Every bitwise operator available will operate on these bits and derive a new value. A bitwise AND operation, for example, will yield a bit value of 1 for every pair of bits that are both on:
const a = 250; // 11111010
const b = 20; // 00010100
a & b; // => 16 // 00010000
We can see that only the fifth bit from the right (that is, 16) is on in both 250 and 20, therefore the AND operation will result in only that bit being left on.
Bitwise operators should only be utilized when you are carrying out binary mathematics. Outside of that, any usage of bitwise operators (for example, for side-effects) should be avoided because it drastically limits the clarity and comprehensibility of our code.
It was not uncommon, for a time, to see bitwise operators such as ~ and | being used in JavaScript because they were popular for succinctly deriving the integer floor of a number (for example, ~34.6789 === 34). It goes without saying that this approach, while clever and ego-boosting, created unreadable and unfamiliar code. It remains preferable to use more explicit techniques. In the case of flooring, using Math.floor() is ideal.