& (Bitwise AND)
Bitwise AND takes bit representations of its two operands, combines bits in pairs by their order, and applies logical AND to each pair. It returns the resulting bit sequence converted back to its decimal form.
For each bit pair, Bitwise AND returns 1
only if both bits are 1
. In all other cases, it returns 0
.
Let's see what's going on here. Suppose we want to apply Bitwise AND to two numbers, 13
and 11
:
1> a & b
What happens when this line is executed?
First, the two values are converted from decimal to binary form:
13
represented in binary is1101
, and11
becomes1011
.Then, each bit of the first number is paired with a corresponding bit of the second number:
Now, the familiar logical AND is applied to each of the bit pairs:
SNIPPET11101 & 21011 == 3 41001
After calculating the result,
1001
, JavaScript converts it back to the decimal value9
and returns:SNIPPET1> 13 & 11 29
| (Bitwise OR)
If you understand Bitwise AND, the next two bitwise operators won't come as a surprise. Everything works the same way -- conversion to binary form, pairing bits from two operands, and subsequent conversion of a result to decimal form -- except that to each bit pair, a different operation is applied.
With Bitwise OR, a | b
returns 1
if either a
or b
is 1
. Again, think of it as of applying the good-old logical OR (||
) to a set of bit pairs.
For example, if we apply Bitwise OR to the same two numbers -- 13 | 11
-- the numbers are first converted to binary form, which results in 1101
and 1011
respectively, and then for each pair, a resulting 1
is returned every time at least one bit in a pair contains a 1
:
11101 |
21011 ==
3
41111
The result, 1111
, is converted to decimal form, and the decimal 15
is returned:
1> 13 | 11
215
^ (Bitwise XOR)
For any given bit pair, Bitwise XOR (a.k.a. Bitwise exclusive OR) returns 1
only if two bits in the pair are different. In all other respects, it works exactly the same as Bitwise AND and Bitwise OR:
11101 |
21011 ==
3
40110
~ (Bitwise NOT)
Bitwise NOT is a little different, as it's applied to one operand, not two. What it does is trivial: after converting the operand to binary, it simply inverts its bits.
There's a quirk though. As we said before, before applying bitwise operators, JavaScript converts an operand to a 32-bit sequence. The leftmost bit in this sequence is used to store the sign of the number: 0
in the leftmost bit means positive, and 1
means negative.
Since Bitwise NOT inverts all 32 bits of its operand, it also inverts its sign: negative turns positive, and vice versa.
For example, here's the entire 32-bit sequence representing the decimal 9
:
100000000000000000000000000001001
Invoking Bitwise NOT (~9
) reverts all bits, which results in:
111111111111111111111111111110110
The leftmost bit now holds 1
, which means the number is negative. The negative number is represented in something called 2's complement, and if you want to know how to use it, here's a quick but very solid summary of how it works.
For now, you want to know that the decimal representation of the resulting number is -10
. In fact, applying Bitwise NOT to any number x
returns -(x + 1)
. For example, ~9
returns -10
, ~-8
returns 7
, and so on.