之前在阅读一些源码时总能看到左位移等一些位操作符,关于位操作符其实很早就有学习过,只不过不理解应用场景,所以看到也不知道为什么要这么使用,但能明白是某种状态声明,这次有时间就了解一下应用场景并简要记录一下
这里只简要说明本文涉及到的位操作符,更多位操作符可看:MDN
过程中涉及到数字不大,容我忽略本应该32位或64位二进制码
左移运算符将数字转为二进制后向左移动n次,并在右侧补n个0
const num = 1;
// 转为二进制 00001
// 向左位移2位 得 00100
console.log(num << 2); // 转十进制:4
按位或运算符将数字转为二进制后 对比每一位数是1则为1
简单说是有1为1,全0为0
const num1 = 1; // 00001
const num2 = 2; // 00010
// 对比每一位 有1反1 得 00011
console.log(num1 | num2); // 转十进制:3
按位与运算符将数字转为二进制后 对比每一位数全1则为1
简单说是全1为1,有0为0
const num1 = 1; // 00001
const num2 = 2; // 00010
// 对比每一位 全1反1 得 00000
console.log(num1 & num2); // 转十进制:0
按位异或运算符将数字转为二进制后 对比每一位数全0为0 不同为1
简单说是相同为0,不同为1
const num1 = 1; // 00001
const num2 = 3; // 00011
// 对比每一位 相同为0 得 00010
console.log(num1 ^ num2); // 转十进制:2
了解了上面的位操作符现在可以尝试应用到场景中进行对比。
假设实现一个权限管理的场景该如何做呢(这里只做模拟权限管理,真实场景权限管理可以参考rbac等设计模型)
这里就用常用的函数封装方法来使用
const user = [1]; // 默认拥有访问权限
const FUNCTION_POINT = {
add: 2,
edit: 3,
delete: 4
}
const addPermission = (type) => {
user.push(FUNCTION_POINT[type]);
}
const checkPermission = (type) => {
return user.includes(FUNCTION_POINT[type]);
}
const deletePermission = (type) => {
const index = user.indexOf(FUNCTION_POINT[type]);
return index >= 0 ? user.splice(index, 1) : '无该权限';
}
addPermission('add');
console.log(checkPermission('edit')); // false
console.log(user); // [1, 2]
if(checkPermission('add')) {
// 执行
console.log("有添加权限");
}
这里使用按位操作符实现,执行效率会比上面更快少了一些查找等操作简洁许多
let user = 1
const FUNCTION_POINT = {
add: 1 << 1,
edit: 1 << 2,
delete: 1 << 3
}
const addPermission = (type) => {
// 这里是在位上添1 的操作
user |= FUNCTION_POINT[type];
}
const deletePermission = (type) => {
// 这里是在位上对比 同1 为0,所以可以作为取消权限操作
user ^= FUNCTION_POINT[type];
}
addPermission('edit');
console.log(user); // 5
deletePermission('edit');
console.log(user); // 1
addPermission('add');
// 判断是否有权限使用&运算符,全1为1 有0为0
// 有权限会运算后 转十进制是1,没有权限是0
if(user & FUNCTION_POINT.add){
// 执行
console.log("有添加权限");
}
我个人认为更好理解上面段代码的方式是:
就是把二进制码中的每一位当作一个状态,不要纠结于这是什么数字,比如下方的权限翻译成成二机制码是这样的
let user = 00001
const FUNCTION_POINT = {
add: 00010,
edit: 00100,
delete: 01000
}
单看位来说,访问权限需要 第一位是1;
添加权限 第二位得是1;
编辑权限第三位得是1;
删除权限第四位得是 1;
二进制码的每一位 0或1都被当做了是否有这个权限
举一个添加权限的例子,就是最开始提到的按位或运算 |
let user = 00001
user | add
翻译一下是
00001
00010
结果:00011
这样就是利用位当作某种状态判断,包括但不限于此次的权限例子
在vue3源码中也使用到了位操作符PatchFlags去做一些组件类型的判断来达到靶向更新的目的,这里就不说多了
附一下vue3源码使用位操作符的链接,感兴趣的小伙伴可以自行研究
vue3 PatchFlags