JavaScript 位运算
位运算在各种语言都有存在,它直接将操作数(operands)当作32位的比特序列(由0和1组成)进行运算。
转换有符号 32 位的比特序列
所有的按位操作符的操作数都会被转成补码(two's complement)形式的有符号32位整数 - MDN
shell
# 十进制的 -314,下面三步执行转化有符号的整数
-314
# 二进制的 314
00000000000000000000000100111010
# 二进制的 314 的反码
11111111111111111111111011000101
# 二进制的 314 的补码(反码 + 1)
11111111111111111111111011000110
补码的操作,使正数开始的最左位始终是 0,负数始终是 1。进行补码操作后,变成当前的最右位。
数字-2147483648
和 2147483647
是32位有符号数字所能表示的最小和最大整数。如果超过该范围,就会截断超出部分,只有 32 位。
基本操作符
位运算就是将两个转化成比特序列的值,按位一一对应,根据操作符逻辑,返回新的值,从而组成一个新值。
&(按位与)
就是对每个位进行 AND 操作,如果都是 1 则返回 1,否则都是 0
shell
3 & 9 = 1
00000000000000000000000000001001 # 9
00000000000000000000000000000011 # 3
00000000000000000000000000000001 # 计算后的结果:1
上面两个值的比对,只有最右位是出现 11 对,其他位都是 10 对或 00 对,所以最终返回 1
|(按位或)
就是对每个位进行 OR 操作,如果都是 0 则返回 0,否则都是 1
shell
3 | 9 = 11
00000000000000000000000000001001 # 9
00000000000000000000000000000011 # 3
00000000000000000000000000001011 # 计算后的结果
^(按位异或)
就是对每个位进行 XOR 操作,如果两个位是不一样的,比如 10,01,则返回 1,否则返回 0
shell
3 ^ 9 = 10
00000000000000000000000000001001 # 9
00000000000000000000000000000011 # 3
~(按位非)
该操作符只作用于一个值,返回目标的反码
shell
~9
00000000000000000000000000001001 # 9
11111111111111111111111111110110 # ~9 的结果:4294967286
<<(左移)
将第一个操作数向左移动指定的位数,向左被移出的位被丢弃,右侧用 0 补充
shell
9 << 2
00000000000000000000000000001001 # 9
00000000000000000000000000100100 # 9 << 2 = 36
在数字 x 上左移 y 比特得到 x * 2y.
9 << 2 = 9 * (2 * 2)
9 << 3 = 9 * (2 * 2 * 2)
>>(有符号右移)
将第一个操作数向右移动指定的位数,向右被移出的位被丢弃,拷贝最左侧的值,补充进左边
shell
9 >> 2
00000000000000000000000000001001 # 9
00000000000000000000000000000010 # 9 >> 2 = 2
>>>(无符号右移)
将第一个操作数向右移动指定的位数,向右被移出的位被丢弃,左侧补充相同位数的 0
shell
9 >>> 2
00000000000000000000000000001001 # 9
00000000000000000000000000000010 # 9 >>> 2 = 2