1. 内容概要本文主要讨论以下两个问题:
- JAVAScript 的位运算:先简单回顾下位运算,平时用的少,相信不少人和我一样忘的差不多了
- 权限设计:根据位运算的特点,设计一个权限系统(添加、删除、判断等)
在讲位运算之前,首先简单看下 JavaScript 中的 Number,下文需要用到 。
在 JavaScript 里,数字均为基于 IEEE 754 标准的双精度 64 位的浮点数,引用维基百科的图片,它的结构长这样:
文章插图
- sign bit(符号): 用来表示正负号
- exponent(指数): 用来表示次方数
- mantissa(尾数): 用来表示精确度
既然讲到这里,就多说一句:0.1 + 0.2 算不准的原因也在于此 。浮点数用二进制表达时是无穷的,且最多 53 位,必须截断,进而产生误差 。最简单的解决办法就是放大一定倍数变成整数,计算完成后再缩小 。不过更稳妥的办法是使用下文将会提到的 math.js 等工具库 。此外还有四种数字进制:
// 十进制1234567890// 二进制:前缀 0b,0B0b10000000000000000000000000000000 // 21474836480b01111111100000000000000000000000 // 21390950400B00000000011111111111111111111111 // 8388607// 八进制:前缀 0o,0O(以前支持前缀 0)0o755 // 4930o644 // 420// 十六进制:前缀 0x,0X0xFFFFFFFFFFFFFFFFF // 2951479051793528300000x123456789ABCDEF // 819855292164869000XA // 10好了,Number 就说这么多,接下来看 JavaScript 中的位运算 。
2.2. 位运算
按位操作符将其操作数当作 32 位的比特序列(由 0 和 1 组成)操作,返回值依然是标准的 JavaScript 数值 。JavaScript 中的按位操作符有:
文章插图
下面举几个例子,主要看下 AND 和 OR:
# 例子1 A = 10001001 B = 10010000A | B = 10011001# 例子2 A = 10001001 C = 10001000A | C = 10001001# 例子1 A = 10001001 B = 10010000A & B = 10000000# 例子2 A = 10001001 C = 10001000A & C = 100010003. 位运算在权限系统中的使用传统的权限系统里,存在很多关联关系,如用户和权限的关联,用户和角色的关联 。系统越大,关联关系越多,越难以维护 。而引入位运算,可以巧妙的解决该问题 。
在讲“位运算在权限系统中的使用”之前,我们先假定两个前提,下文所有的讨论都是基于这两个前提的:
- 每种权限码都是唯一的(这是显然的)
- 所有权限码的二进制数形式,有且只有一位值为 1,其余全部为 0(2^n)
- | 可以用来赋予权限
- & 可以用来校验权限
权限 字母表示 数字表示 二进制 读 r 4 0b100 写 w 2 0b010 执行 x 1 0b001
可以看到,权限用 1、2、4(也就是 2^n)表示,转换为二进制后,都是只有一位是 1,其余为 0 。我们通过几个例子看下,如何利用二进制的特点执行权限的添加,校验和删除 。
3.1. 添加权限
let r = 0b100let w = 0b010let x = 0b001// 给用户赋全部权限(使用前面讲的 | 操作)let user = r | w | xconsole.log(user)// 7console.log(user.toString(2))// 111// r = 0b100// w = 0b010// r = 0b001// r|w|x = 0b111可以看到,执行 r | w | x 后,user 的三位都是 1,表明拥有了全部三个权限 。
Linux 下出现权限问题时,最粗暴的解决方案就是 chmod 777 xxx,这里的 7 就代表了:可读,可写,可执行 。而三个 7 分别代表:文件所有者,文件所有者所在组,所有其他用户 。3.2. 校验权限
刚才演示了权限的添加,下面演示权限校验:
let r = 0b100let w = 0b010let x = 0b001// 给用户赋 r w 两个权限let user = r | w// user = 6// user = 0b110 (二进制)console.log((user & r) === r) // true 有 r 权限console.log((user & w) === w) // true 有 w 权限console.log((user & x) === x) // false 没有 x 权限如前所料,通过 用户权限 & 权限 code === 权限 code 就可以判断出用户是否拥有该权限 。
3.3. 删除权限
我们讲了用 | 赋予权限,使用 & 判断权限,那么删除权限呢?删除权限的本质其实是将指定位置上的 1 重置为 0 。上个例子里用户权限是 0b110,拥有读和写两个权限,现在想删除读的权限,本质上就是将第三位的 1 重置为 0,变为 0b010:
推荐阅读
- 国都证券|面试中的奇葩事
- 2022第三代社保卡有几个密码,第三代社保卡密码是几位数
- 茶水在食疗养生中的妙用
- 三星堆遗址以高度发达的青铜文明著名于世 我国西南地区的青铜时代遗址三星堆位于哪个省
- 淘宝店铺定位的要素 淘宝店铺的市场定位
- 单位体检一半人都有肺结节吗,单位体检过程中发现肺部结节会现场告诉吗
- 水浒传中的王婆茶坊
- 什么星座中的七颗亮星组成一个勺子的形状 北斗七星是勺子形状的吗
- 如何挑选优质益母草茶
- 雪天开车手动挡下坡用几档 下雪天开车用什么档位