Skip to content

JavaScript 位运算

位运算在各种语言都有存在,它直接将操作数(operands)当作32位的比特序列(由0和1组成)进行运算。

转换有符号 32 位的比特序列

所有的按位操作符的操作数都会被转成补码(two's complement)形式的有符号32位整数 - MDN

shell
# 十进制的 -314,下面三步执行转化有符号的整数
-314
# 二进制的 314
00000000000000000000000100111010
# 二进制的 314 的反码
11111111111111111111111011000101
# 二进制的 314 的补码(反码 + 1)
11111111111111111111111011000110

补码的操作,使正数开始的最左位始终是 0,负数始终是 1。进行补码操作后,变成当前的最右位。

数字-21474836482147483647 是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

参考资料

  1. Mdn
  2. 掘金-位运算符在JS中的妙用
  3. 掘金-JavaScript 那些写出来会被同事揍的骚操作