说在前面
日常的系统中,经常需要给用户做权限控制。一般的做法是,为每种权限分配一个id,然后把权限组合成一个数组。每次需要判断权限,组合权限的时候都需要进行数组操作。
最近刷视频,看vue3,其中有提到在Vue3中,模板静态化分析的时候会给模板用数字标记类型。然后再使用的时候是通过位运算来判断标记类型需要做哪些操作。显然位运算会比数组操作速度来的更快。当时看到弹幕一片懵逼,好像这种权限控制方式有点绕。
位运算如何实现权限管理
2的N次方定义权限
定义权限需要是2的N次方。
可以直接写
var ADD = 1; // 增加权限
var UPD = 2; // 修改权限
var SEL = 4; // 查找权限
var DEL = 8; // 删除权限
也可以像vue里面一样通过通过 << 零填充左位移符号来定义。因为在二进制中,1后面补0,结果就是2的N次方。
export const emun PatchFlags {
TETX = 1,
CLASS = 1 << 1,
STYPE = 1 << 2,
PROPS = 1 << 3,
FULL_PROPS = 1 << 4,
...
}
需要这样做的原理是,有且只有一个1的二进制数表示一种权限。如果有多个1那么这个二进制表示多种权限。每一位表示一种权限。
0001 增加权限
0010 修改权限
0100 查找权限
1000 删除权限
例如 “|” OR 添加权限
通过二进制OR 运算来组合两个权限。
var A = ADD | UPD | SEL | DEL; // A 拥有增删改查权限
进行OR操作(OR操作只要有一个是1,那么结果就是1)
0001
0010
0100
1000
=1111
1111就表示了增删改查权限
利用 “&” AND 和 “~” 取反 删除权限
var A = ADD | UPD | SEL | DEL; // A 拥有增删改查权限
A = A & ~DEL; // A删除了DEL权限
DEL进行~取反操作
1000 DEL
= (1)1000 ~DEL
然后进行 & AND 操作
1111 增删改查
(1)1000 ~DEL
= 0111 新的权限已经没有了 DEL权限了。
判断权限
判断一个权限组是否包含某个权限,直接进行 & AND操作就好了。如果操作结果大于1,就表示拥有权限。
var A = ADD | UPD | SEL | DEL; // A 拥有增删改查权限
A = A & ~DEL; // A删除了DEL权限
console.log((A & DEL)>0) // false
console.log((A & ADD)>0) // true
结果是0 自动转换位false
0111 A权限组
1000 DEL
=0000 AND操作,只要有一位是0,结果就是0
结果是1 自动转换位true
0111 A权限组
0001 ADD权限
=0001
最后,因为每一种权限都占了一个二进制位。所以这种方式并不适合超大权限集合。因为二进制位数是有限的(32位?所以最多支持32个权限···)。