学习一波位运算

158 阅读5分钟

最近在看vue3的源码,看到ShapeFlags的定义中有<<符号,一时之间不知道这个是什么,查了下才知道这个是位运算。于是,准备学习一波js中的位运算。

  • 左移操作符(<<): 将第一个操作数向左移动指定位数,左边超出的位数将会被清除,右边将会补零。 需要将数先转成二进制后再进行位移操作
const a = 5;         // 00000000000000000000000000000101
const b = 2;         // 00000000000000000000000000000010

console.log(a << b); // 00000000000000000000000000010100
// Expected output: 20
  • 右移操作符(>>): 将一个操作数按指定移动的位数向右移动,右边移出位被丢弃,左边移出的空位补符号位(最左边那位)。
const a = 5;          //  00000000000000000000000000000101
const b = 2;          //  00000000000000000000000000000010
const c = -5;         //  11111111111111111111111111111011

console.log(a >> b);  //  00000000000000000000000000000001
// Expected output: 1

console.log(c >> b);  //  11111111111111111111111111111110
// Expected output: -2
  • 按位与操作符(&): 在两个操作数对应的二进位都为 1 时,该位的结果值才为 1。
const a = 5;        // 00000000000000000000000000000101
const b = 3;        // 00000000000000000000000000000011

console.log(a & b); // 00000000000000000000000000000001
// Expected output: 1
  • 按位与赋值运算符(&=): 将两个数的二进制进行按位与运算并将结果赋值给变量
let a = 5;      // 00000000000000000000000000000101
a &= 3;         // 00000000000000000000000000000011

console.log(a); // 00000000000000000000000000000001
// Expected output: 1
  • 按位非运算符(~): 将操作数的位反转。会将操作数转化为 32 位的有符号整型。
const a = 5;     // 00000000000000000000000000000101
const b = -3;    // 11111111111111111111111111111101

console.log(~a); // 11111111111111111111111111111010
// Expected output: -6

console.log(~b); // 00000000000000000000000000000010
// Expected output: 2
  • 按位或运算符(|): 其中一个或两个操作数对应的二进制位为 1 时,该位的结果值为 1。
const a = 5;        // 00000000000000000000000000000101
const b = 3;        // 00000000000000000000000000000011

console.log(a | b); // 00000000000000000000000000000111
// Expected output: 7
  • 按位或赋值运算符(|=): 使用两个操作数的二进制表示,对它们执行按位或运算并将结果分配给变量。
let a = 5;      // 00000000000000000000000000000101
a |= 3;         // 00000000000000000000000000000011

console.log(a); // 00000000000000000000000000000111
// Expected output: 7
  • 按位异或运算符(^): 在两个操作数有且仅有一个对应的二进制位为 1 时,该位的结果值为 1。
const a = 5;        // 00000000000000000000000000000101
const b = 3;        // 00000000000000000000000000000011

console.log(a ^ b); // 00000000000000000000000000000110
// Expected output: 6
  • 按位异或运算符(^=): 使用二进制表示操作数,进行一次按位异或操作并赋值。
let a = 5;      // 00000000000000000000000000000101
a ^= 3;         // 00000000000000000000000000000011

console.log(a); // 00000000000000000000000000000110
// Expected output: 6

因为位操作符都需要先将数字转成二进制的,而我们日常接触的都是十进制的,JS原生也提供了这种进制转换的方法。

  • 十进制转二进制
a = 5;
// 将十进制转成给定长度的二进制
a.toString(2).padStart(32, 0) // 00000000000000000000000000000101
  • 二进制转十进制
a = 100;
parseInt(a, 2); // 第二个参数表示给定数字的基数,取值范围为2~36,默认为10

注: 这两个方法对负数的处理有问题,因为它们会保留负数的符号而不是将第一位的符号位设置为1。