位运算,默默无闻而不被人关注,但却在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
得到反码后,1变0️,0变1
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次方,然后向下取整