一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
之前在学习 Linux 时, 发现对用户对文件的操作权限是使用 10进制 的数字表示的,其实在 TS 中的数字枚举也支持类似的功能。
位枚举(枚举的位运算)
主要是针对 数字枚举
举个栗子
有这样一种场景
创建一个用户权限的枚举,使用 数字枚举 进行约束。
enum Permissions {
Read, //可读权限
Write, //可写权限
Create, //可以创建权限
Delete, //可以删除权限
}
这就创建了一个 权限枚举, 但是存在一些问题
假如我需要对权限进行组合, 一个用户 有可读、可写的权限,没有创建、删除权限, 那该怎么完成权限的组合呢?
权限组合
方法一
可以给枚举添加跟多的权限名
enum Permissions {
Read, //可读权限
Write, //可写权限
Create, //可以创建权限
Delete, //可以删除权限
ReadWrite, //可读可写权限
...
}
这种方法可以解决问题,但是书写很麻烦, 权限的情况种类太多, 之后增加新的枚举字段 不容易扩展 不推荐使用
方法二
利用 TS 的枚举位运算 (本质也是使用 js 的能力)
解析
enum Permissions {
Read = 1, //可读权限
Write = 2, //可写权限
Create = 4, //可以创建权限
Delete = 8, //可以删除权限
}
相信数学比较好的同学能发现规律, 1、2、4、8 都是 2^n, 把它们转化为二进制。
| 十进制 | 二进制 | 权限 |
|---|---|---|
| 1 | 0001 | 可读 |
| 2 | 0010 | 可写 |
| 4 | 0100 | 可创建 |
| 8 | 1000 | 可以删除 |
其中只有一个 1 其余都是 0
此时就可以使用 十进制权限想加来表示权限
举个栗子
一个用户的权限为 3, 3的二进制为 0011, 对应上面的表格, 该用户拥有 可读,可写权限。
因此可以通过基本权限来组成新的权限
如何组合权限
用户有可读、可删除的权限, 怎么使用 TS 表达出来呢?
//使用位运算
const readAndDelete: Permissions = Permissions.Read | Permissions.Delete
位运算 两个数字换算成二进制后进行的运算,产生一个新的二进制
| 表示 或运算 : 将两个二进制进行比较,两个二进制在相同的 位置上 其中有一个是 1 产生新的二进制该位也就是 1,否则是 0
举个栗子
1 和 8进行位运算,将十进制转化为 二进制为 0001 1000
| 十进制 | 3位 | 2位 | 1位 | 0位 |
|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 1 |
| 8 | 1 | 0 | 0 | 0 |
| 结果 | 1 | 0 | 0 | 1 |
位运算之后的结果为 1001 转为十进制为 9, 所以 9 可以表示 可读、可删除的权限。
如何判断是否拥有某个权限
如果用户的权限为 10 怎么判断拥有某一个权限
原理: 判断二进制在用一位上 是否都是 1 的结果和权限判断是否相等。
/**
* 判断 target 时候拥有 per 权限
* @param target 目标
* @param per 判断值
*/
function hasPermissions(target: Permissions, per: Permissions): boolean {
return (target & per) === per
}
hasPermissions(10, Permissions.Read) //false 没有可读权限
hasPermissions(10, Permissions.Write) //true 有可写权限
& 表示 且运算:将两个二进制进行比较,两个二进制在相同的 位置上 其中都为 1 产生新的二进制该位也就是 1,否则是 0
画图解释
如何删除某个权限
如果用户的权限为 10 怎么删除该用户的可读权限
原理: 判断二进制在用一位上 是否都是 1 如果是代表拥有这个权限。
/**
* target 删除 per 权限
* @param target 目标
* @param del 删除的权限值
*/
function deletsPermissions(target: Permissions, del: Permissions) {
return target ^ del
}
let p = 10;
p = deletsPermissions(p, Permissions.Write); //删除可写权限
console.log(hasPermissions(p, Permissions.Write)); //false
^ 表示 异或运算:将两个二进制进行比较,两个二进制在相同的 位置上 相等, 产生新的二进制该位也就是 0,否则是 1
画图解释
总结
在前端可能不会使用到此手段, 如果某一天需要处理权限的问题请想起它, 它十分优雅其极度具有扩展性。