前端 --- Linux二进制权限,逻辑位运算符 & 和 | 在权限中的应用

441 阅读3分钟

Linux二进制权限在前端中的应用

需求

修改权限模块,逻辑方面倒是没花太多时间,加上画新的ui一天就差不多搞定了,可是我看到一个这么一个东西

(record.permission & PERMISSION_ACTION[type]) > 0 // 代码经过简化

我知道这是位与运算符,不知道的请 => MDN详解: 表达式与运算符 - JavaScript | MDN

但是从来没有在实践中使用过这个东西。花了点时间研究了一下,发现这是Linux的二进制权限,接下来展开说下实际应用

首先把权限的权重分为五个档位,用数字表示就是1,2,4,8,16

问题1:为啥不分成1、2、3、4、5呢?

解答:好问题,我一开始也是这么想的,反正对于我来说,每个档位有一个唯一值类似id的东西就可以进行判断了,想到这里膜拜一波Linux的智慧,不过这也是我的知识盲区(我是从平面转到前端的。

我们现在有五个档位的权限,查看、创建、编辑、删除、下载,分别对应档位1、2、4、8、16

每后面一个的权限都包含前面所有的权限,比如有创建权限,那肯定有查看权限吧,有编辑权限,那就也有查看和创建权限,以此类推。

权限变动后我们发给后端的数据不是['查看'、'创建'、'编辑'、'删除'、'下载']这种被选中的值的数组,而是权限的权重和(1、3、7、15、31),我选中的是编辑,那我的权限值就是7。

  • 1 => 查看 1 = 1
  • 3 => 查看\创建 1+2 = 3
  • 7 => 查看\创建\编辑 1+2+4 = 7
  • 15 => 查看\创建\编辑\删除 1+2+4+8 = 15
  • 31 => 查看\创建\编辑\删除\下载 1+2+4+8+16 = 31
十进制二进制次幂
10000012^0
30000112^2-1
40001002^2
70011112^3-1
80010002^3
150111112^4-1
160100002^4
310111112^5-1
321000002^5

问题1 总结

3、7、15、31分别包含之前所有的权限,我们在二进制的角度下会发现他们都是2的次幂减1

这个时候通过我上面说到的逻辑与运算符,就可以判断权限的包含关系

例子:

3&1 //1
3&2 //2
7&1 //1
7&2 //2
7&4 //4 
7&16 //0
// 大于0就是包含前置权限,等于0就是不包含
......

这样通过权重和就可以去进行前置权限的判断

问题2:如何通过后端返的权限值()获取选中的权限?Switch吗?

不,Switch太麻烦也不易维护,我们有比它更好的办法

&运算符(位与),简述:两个二进制上下比较,都为1才是1

// 定义各权限的键值对
const PERMISSION_ACTION = {
  VIEW: 1 << 0,
  ADD: 1 << 1,
  MODIFY: 1 << 2,
  DELETE: 1 << 3,
  DOWNLOAD: 1 << 4
};

// 通过权限和获取对应的权限
const getPermissionTypes = (permission: number)=>{
    return ['VIEW','ADD','MODIFY','DELETE','DOWNLOAD'].filter((type)=>{
        if(permission & PERMISSION_ACTION[type]) return type;
    })
}

在控制台跑了一下,没问题,getPermissionTypes函数就能帮我们获取到权限值相对应的权限

image.png

问题3:如何通过选中的权限名字获得其权限值及其前置权限的和?

我选中了删除权限,那么我的权限值应该是1+2+4+8 = 15,对吧

这里我们用 | 运算符(位或), 简述:两个二进制比较,有一个为1就是1

以下是实现

// 权限类型
const PERMISSION_TYPE = [
  // 预览权限
  'VIEW',
  // 新增权限
  'ADD',
  // 修改权限
  'MODIFY',
  // 删除权限
  'DELETE',
  // 下载权限
  'DOWNLOAD'
];

// 定义各权限的键值对
const PERMISSION_ACTION = {
  VIEW: 1 << 0,
  ADD: 1 << 1,
  MODIFY: 1 << 2,
  DELETE: 1 << 3,
  DOWNLOAD: 1 << 4
};

// 通过选中的权限获取其与所有前置权限
const getPerssionNum = (permissions: PermissionType[]) => {
  let res: number = 0;
  permissions.forEach((key) => {
    res = res | PERMISSION_ACTION[key];
  });

  return res;
};

想了解更多,百度 Linux二进制权限

以上就是全部,有问题反馈