JavaScript 中的二进制散列值和权限设计

简介: 这篇文章介绍了JavaScript中使用位运算符进行权限控制的方法。文章首先介绍了JavaScript中的进制类型,包括十进制、二进制、十六进制和八进制。然后解释了位运算符的概念和常用的按位与、按位或、按位异或和按位非操作符。接下来讨论了位运算符在传统权限系统中的应用场景,并给出了一个基于二进制变量表示权限的示例。最后,文章提到了位运算符方案的局限性,例如每个权限码必须是唯一且只有一位为1的限制。但总的来说,在中小型业务中可以使用这种方式进行权限控制。

不管是前端还是后端的伙伴,在工作中会经常遇到权限控制的场景,业务上无非就几种权限:页面权限、操作权限、数据权限,不同公司根据业务需要都采取不同的方法区控制权限,我们这里讨论一下使用 JavaScript 中的位运算符来控制权限。

进制类型

JavaScript 中提供的进制表示方法有四种:十进制、二进制、十六进制、八进制
对于数值字面量,主要使用不同的前缀来区分:

  1. 十进制:取值数字 0-9;不用前缀。
  2. 二进制(Binary): 取值数字 0 和 1 ;前缀 0b 或 0B。
  3. 十六进制(Hexadecimal):取值数字 0-9 和 a-f ;前缀 0x 或 0X。
    1. 八进制(Octal):取值数字 0-7 ;前缀 0o 或 0O (ES6规定)。

位运算符

什么是位运算符?
位运算符指的是二进制位的运算,先将十进制数转成二进制后再进行运算。 在二进制位运算中,1表示true,0表示false。
JavaScript 中的按位操作符有:

运算符 用法 描述
按位与(AND) A & B 如果对应的二进制位都为 1,则该二进制位为 1
按位或(OR) A 或 B 如果对应的二进制位有一个为 1,则该二进制位为 1
按位异或(XOR) A ^ B 如果对应的二进制位只有一个为 1,则该二进制位为 1
按位非(NOT) ~A 反转所有二进制位,即 1 转换为 0,0 转换为 1
按位左移 A << B 将所有二进制位统一向左移动指定的位数,并在最右侧补 0
按位右移 A >> B 按位右移(有符号右移):将所有二进制位统一向右移动指定的位数,并拷贝最左侧的位来填充左侧
无符号右移 A >>> B 按位右移零(无符号右移):将所有二进制位统一向右移动指定的位数,并在最左侧补 0

示例:

const A = 0101,B = 0001
// 按位与(AND)
A & B = 0001

// 按位或(OR)
A | B = 0101

// 按位异或(XOR)
A ^ B = 0100

// 按位非(NOT)
~A = 1010

// 按位左移
A << 1 = 1010

// 按位右移
A >> 1 = 0010

// 无符号右移
A >>> 1 = 0010

位运算符在工作中的应用得比较少,但有时候它可以很巧妙地解决我们工作中一些问题。

运用场景

在传统的权限系统中,不同的权限之间存在很多关联关系,而且有很多种权限组合方式,在这种情况下,权限就越难以维护。这种情况我们就可以使用位运算符,可以很巧妙地解决这个问题。

假设我们现在权限系统中有4种基本权限:可读、可写、创建、删除
那么我们可以定义4个二进制变量表示:

// 所有权限码的二进制数形式,有且只有一位值为 1,其余全部为 0
const READ = 0b1000 // 可读
const WRITE = 0b0100 // 可写
const CREATE = 0b0010 // 创建
const DELETE = 0b0001 // 删除

权限操作

  1. 使用 按位或(OR) 添加权限:

    // 赋予用户全部权限
    const ALL = READ | WRITE | CREATE | DELETE 
    
    console.log(ALL)
    // 结果位 1111,每个位置的1就代表拥有这个权限,这里全部是1,就代表拥有全部权限。
    
    // 同样的,这些权限可以自由组合
    const READ_AND_WRITE = READ | WRITE  // 可读和可写,结果为 1100
    const READ_AND_CREATE = READ | CREATE  // 可读和创建,结果为 1010
    const WRITE_AND_DELETE = WRITE | DELETE  // 可写和删除,结果为 0101
    
  2. 使用 按位与(AND) 校验权限:

    // 比如我们拿到一个用户的权限,我们怎么根据返回的数据判断是否拥有某个权限呢?
    
    // 假设现在返回了 拥有可读可写的权限组合:1100
    const auth = READ | WRITE  // 可读和可写,结果为 1100
    
    // 判断是否包含 READ 权限
    const isRead = (auth & READ) === READ // true
    
    // 是否包含 DELETE 权限
    const isDelete = (auth & DELETE) === DELETE // false
    
  3. 使用 按位非(NOT) 剔除权限:

    // 全部权限
    const ALL = READ | WRITE | CREATE | DELETE 
    
    // 如果要剔除 WRITE 权限,应该怎么做呢,先执行 ~ 取反,再执行 & 运算
    const notWrite = ALL & ~WRITE // 输出 1011
    // 剔除 DELETE 权限
    const notDelete = ALL & ~DELETE // 输出 1110
    

局限性

本文提到的这种位运算符方案,有一定的前提条件:

  1. 每种权限码都是唯一的,有且只有一位值为 1。
  2. 一个数字的范围只能在 -(2^53 -1) 和 2^53 -1 之间,如果权限系统设计得比较庞大,这种方式可能不合适。

不过总的来说,这种方式在中小型业务中应该够用了。

相关文章
|
30天前
|
JavaScript 前端开发 数据处理
掌握JavaScript中的二进制运算,提升你的编程技能!
掌握JavaScript中的二进制运算,提升你的编程技能!
|
1月前
|
存储 自然语言处理 前端开发
详谈JavaScript 二进制家族:Blob、File、FileReader、ArrayBuffer、Base64
详谈JavaScript 二进制家族:Blob、File、FileReader、ArrayBuffer、Base64
80 1
|
1月前
|
存储 移动开发 自然语言处理
谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64(下)
谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64(下)
|
1月前
|
XML JavaScript 前端开发
谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64(上)
谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64(上)
|
算法 JavaScript 前端开发
【JavaScript数据结构与算法】字符串类(计算二进制子串)
【JavaScript数据结构与算法】字符串类(计算二进制子串)
|
存储 JavaScript 前端开发
Javascript 操作二进制数据
一个类型化数组(TypedArray)对象描述了一个底层的二进制数据缓冲区
71 0
Javascript 操作二进制数据
|
Web App开发 JavaScript 前端开发
JavaScript 技术篇-navigator.permissions读取chrome剪切板权限获取不生效原因:只有在https协议下使用有效。手动设置chrome页面剪切板读取权限方法
JavaScript 技术篇-navigator.permissions读取chrome剪切板权限获取不生效原因:只有在https协议下使用有效。手动设置chrome页面剪切板读取权限方法
1250 0
JavaScript 技术篇-navigator.permissions读取chrome剪切板权限获取不生效原因:只有在https协议下使用有效。手动设置chrome页面剪切板读取权限方法
|
Web App开发 存储 JSON
JS的二进制家族:Blob的具体介绍
Data URL对大家来说并不陌生,Web性能优化有一项措施:把小图片用base64编码直接嵌入到HTML文件中,实际就是利用了Data URL来获取图片数据。
|
JSON JavaScript 前端开发
JS的二进制家族:ArrayBuffer的具体介绍
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
|
存储 XML 前端开发
JS的二进制家族:Blob、ArrayBuffer和Buffer
ArrayBuffer:前端的一个通用的二进制缓冲区,类似数组,但在API和特性上却有诸多不同
JS的二进制家族:Blob、ArrayBuffer和Buffer