在思否上遇到一个问位运算符的问题 字符串的位运算,是怎么执行的,我也挺好奇的,就是为啥字符串进行位运算的时候返回的结果是 0
,索性在解答这个问题的同时把位运算符都整理一遍。
那么先来整理一下位运算符,最后再说明为什么字符串的处理结果为 0
位运算符
按位与 AND &
a & b
在 a, b 的位表示中,每一个对应的位都为 1 则返回 1 , 否则返回 0。
10 & 5 // 1010 & 0101 => 0000
// logs 0
按位或 OR |
a | b
在 a, b 的位表示中,每一个对应的位,只要有一个为 1 则返回 1 , 否则返回 0。
10 | 5 // 1010 | 0101 => 1111
// logs 15
按位异或 XOR ^
a ^ b
在 a, b 的位表示中,每一个对应的位,两个不相同则返回 1,相同则返回 0。
15 ^ 5 // 1111 ^ 0101 => 1010
// logs 10
按位非 NOT ~
~ a
反转被操作数的位。
这里就不能像上边这样简写了,需要完整书写32位,再反转。
~ 1 // ~ 00000000000000000000000000000001 => 11111111111111111111111111111110
// logs -2
就是把运算数转换为 32 位的二进制整数,然后逐位进行取反操作,最后返回十进制浮点数
左移 shift <<
a << b
将 a 的二进制串向左移动 b 位,右边移入 0。
5 << 2 // 0101 << 2 => 010100
// logs 20
简单来说就是整个二进制串向左移动,如果超出就被丢弃,然后末尾补充 0,举个负数例子可能会清晰很多
-113 << 4 // 11111111111111111111111110001111 << 4 => 11111111111111111111100011110000
// logs -1808
算术右移 >>
a >> b
把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位。
译注:算术右移左边空出的位是根据最高位是 0 和 1 来进行填充的
10 >> 2 // 1010 >> 2 => 10
// logs 2
和左移一样的处理思路,只不过方向反过来,并且按照首位来填充,如果是1则填充1,0则填充0
-2 >> 4 // 11111111111111111111111111111110 >> 4 => 11111111111111111111111111111111
// logs -1
2147483647 >> 4 // 01111111111111111111111111111111 >> 4 => 00000111111111111111111111111111
// logs 134217727
无符号右移 >>>
a >>> b
把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位,并把左边空出的位都填充为 0。
这个挺好理解的,比算术右移方便记,只需要填0就好了。
-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