JavaScript 中的位运算符

在思否上遇到一个问位运算符的问题 字符串的位运算,是怎么执行的,我也挺好奇的,就是为啥字符串进行位运算的时候返回的结果是 0,索性在解答这个问题的同时把位运算符都整理一遍。

那么先来整理一下位运算符,最后再说明为什么字符串的处理结果为 0


位运算符

按位与 AND &

a & b 在 a, b 的位表示中,每一个对应的位都为 1 则返回 1 , 否则返回 0。

1
2
10 & 5 // 1010 & 0101 =>  0000
// logs 0

按位或 OR |

a | b 在 a, b 的位表示中,每一个对应的位,只要有一个为 1 则返回 1 , 否则返回 0。

1
2
10 | 5 // 1010 | 0101 =>  1111
// logs 15

按位异或 XOR ^

a ^ b 在 a, b 的位表示中,每一个对应的位,两个不相同则返回 1,相同则返回 0。

1
2
15 ^ 5 // 1111 ^ 0101 => 1010
// logs 10

按位非 NOT ~

~ a 反转被操作数的位。

这里就不能像上边这样简写了,需要完整书写32位,再反转。

1
2
~ 1 // ~ 00000000000000000000000000000001 => 11111111111111111111111111111110
// logs -2

就是把运算数转换为 32 位的二进制整数,然后逐位进行取反操作,最后返回十进制浮点数

左移 shift <<

a << b 将 a 的二进制串向左移动 b 位,右边移入 0。

1
2
5 << 2 // 0101 << 2 => 010100
// logs 20

简单来说就是整个二进制串向左移动,如果超出就被丢弃,然后末尾补充 0,举个负数例子可能会清晰很多

1
2
-113 << 4 // 11111111111111111111111110001111 << 4 => 11111111111111111111100011110000
// logs -1808

算术右移 >>

a >> b 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位。
译注:算术右移左边空出的位是根据最高位是 0 和 1 来进行填充的

1
2
10 >> 2 // 1010 >> 2 => 10
// logs 2

和左移一样的处理思路,只不过方向反过来,并且按照首位来填充,如果是1则填充1,0则填充0

1
2
3
4
-2 >> 4 // 11111111111111111111111111111110 >> 4 => 11111111111111111111111111111111
// logs -1
2147483647 >> 4 // 01111111111111111111111111111111 >> 4 => 00000111111111111111111111111111
// logs 134217727

无符号右移 >>>

a >>> b 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位,并把左边空出的位都填充为 0。

这个挺好理解的,比算术右移方便记,只需要填0就好了。

1
2
3
4
-2 >>> 4 // 11111111111111111111111111111110 >> 4 => 00001111111111111111111111111111
// logs 268435455
100 >>> 4 // 1100100 >> 4 => 0000100
// logs 6

回到最初的问题

为什么字符串进行位运算的时候返回的结果是 0

位操作符在移位前做了两种转换,第一步,将不是 number 类型的数据转换为 number,第二步,将 number 转换为无符号的 32bit 数据,也就是 Uint32 类型。

字符串转换为 number 会失败,所以返回 0,最终操作的时候其实是在操作 0

表达式与运算符 - JavaScript | MDN
JS中表达式 >>> 0 浅析 - SegmentFault
What is the JavaScript >>> operator and how do you use it? - Stack Overflow