基础-位运算的强大

100 阅读4分钟

位运算,默默无闻而不被人关注,但却在js开发中发挥着举足轻重的作用。

位运算的执行效率是非常快的,能给我们的开发带来很多方便。位运算,指的是将一个整数的二进制格式进行运算。JS中,如果对一个数据进行位运算,它首先会将其转换为一个整数(抹掉小数), 并且按照32位的整数二进制进行排列。 例如:

2.3 -> 2 -> 0000 0000 0000 0000 0000 0000 0000 0010
NaN -> 0
Infinity -> 0
-Infinity -> 0

1. 位与运算 &

写法:数1 & 数2; 将两个整数的每一位进行比较,如果都为1,则结果为1,否则结果为0。 例如:

// 1: 0000 0000 0000 0000 0000 0000 0000 0001
// 2: 0000 0000 0000 0000 0000 0000 0000 0010
// 一位一位地进行比较
// result: 0000 0000 0000 0000 0000 0000 0000 0000
console.log(1 & 2); //0

// 2:10
// 3:11
console.log(2 & 3); //10 -> 2

// 2:010
// 4:100
console.log(2 & 4); //000 -> 0

2. 位或运算 |

写法:数1 | 数2; 将两个整数的每一位进行比较,如果都为0,则结果为0,否则结果为1。 例如:

// 1: 0000 0000 0000 0000 0000 0000 0000 0001
// 2: 0000 0000 0000 0000 0000 0000 0000 0010
// 一位一位地进行比较
// result: 0000 0000 0000 0000 0000 0000 0000 0011
console.log(1 | 2); //11 -> 3

// 2:10
// 3:11
console.log(2 | 3); //11 -> 3

// 2:010
// 4:100
console.log(2 | 4); //110 -> 6

3. 位非运算 ~

写法:~数;将该整数按位取反,就是1变为0,0变为1

补充:计算机基础

例如:-1

// 负数,第一位,即符号位为1,则为负数。
真码:1000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1110 //真码取反
补码:1111 1111 1111 1111 1111 1111 1111 1111 //反码加1 计算机的最终储存

例如:~1

1: 0000 0000 0000 0000 0000 0000 0000 0001
反码:1111 1111 1111 1111 1111 1111 1111 1101 //取反并减1

得到反码后,10️,01

console.log(~1); // -2

取反快速运算:-取反的数字 -1;例如,~2,即-2 - 2= -3;~-2,即-(-2) - 1 = 1

快速取反:

  console.log(~~4.434155);//4

4. 异或运算 ^

写法:数1 ^ 数2;将两个整数按位进行比较,不同取1,相同取0。 例如:

1: 01
2: 10
console.log(1^2); // 11 -> 3

炫技交换变量:

  let a = 2;
  let b = 4;
  a = a ^ b;
  b = a ^ b;
  a = a ^ b;
  console.log("a,b", a, b);// 4 2

5. 应用场景

位的叠加(位的开关)。

权限配置:

// 使用 2 的倍数
 const permission = {
    read: 1, //读权限
    edit: 2, //编辑(修改)权限
    create: 4, //创建权限
  };
  
  // 用 二进制 来表示
  const permission = {
    read: 0b0001, 
    edit: 0b0010, 
    create: 0b0100, 
  };

权限判断:

 // 保存可读 可写
  const p = permission.read | permission.edit; // 011 -> 3;
  //判断权限 p 是有 可读权限
  const res = p & (permission.read === permission.read) ? "可读" : "不可读"; 
  console.log('res',res);// 可读
  
  // 保存可创建 可写
  const g = permission.create | permission.edit; // 110 -> 6
  //判断权限 g 是有 可读权限
  const res1 = g & (permission.read === permission.read) ? "可读" : "不可读";
  console.log("res1", res1);//不可读

去掉权限:


  // 保存可读 可写
  let p = permission.read | permission.edit; // 011 -> 3

  //去掉权限
  p = (p | permission.read) ^ permission.read;

  //判断权限 p 是有 可读权限
  const res = (p & permission.read) === permission.read ? "可读" : "不可读";
  console.log("res", res); // 不可读

6. 位移运算

  • 左位移:<<

    写法:数1 << 数2;将数字1的二进制(除符号位外),向左移动数字2的次数 例如:

 console.log("3 << 1", 3 << 1); // 0011 -> 0110 -> 6;
 
 结论:
 // f = x << y
 // f = x * 2^y
  • 右位移: >>

写法:数1 >> 数2;将数字1的二进制(除符号位外),向右移动数字2的次数 例如:

```js
 console.log("3 >> 1", 3 >> 1); // 0011 -> 0001 -> 1;
 
 结论:
 // f = x >> y
 // f = Math.floor(x/2*y)
 // 除以2的y次方,然后向下取整