likes
comments
collection
share

通过学习 React 源码,使用位运算来实现权限管理,实在是太简单了 😉😉😉

作者站长头像
站长
· 阅读数 21

在 React 中,lane 是用来标识更新优先级的位掩码,它可以在频繁运算的时候占用内存少,计算速度快。每个 lane 代表一种优先级级别,React 可以同时处理多个 lane,通过这种方式来管理不同优先级的任务。

位运算的基本操作

以下是位运算的一些基本操作的详细讲解,包括与(AND)、或(OR)、异或(XOR)、取反(NOT)、左移(Left Shift)、右移(Right Shift)操作:

  1. 与(AND): 对应位都为 1 时,结果为 1,否则为 0。

  2. 或(OR): 对应位只要有一个为 1,结果就为 1。

  3. 异或(XOR): 对应位不同,结果为 1,相同为 0。

  4. 取反(NOT): 将每一位取反,0 变 1,1 变 0。

  5. 左移(Left Shift): 将二进制数的位向左移动,右边补 0。

  6. 右移(Right Shift): 将二进制数的位向右移动,左边补符号位(正数补 0,负数补 1)。

如下是使用位运算的一些基本操作,它包括与(AND)、或(OR)、异或(XOR)、取反(NOT)、左移(Left Shift)、右移(Right Shift)操作:

// 与(AND)操作
const a = 5; // 二进制: 0101
const b = 3; // 二进制: 0011
const andResult = a & b;

console.log(`${a} & ${b} = ${andResult}`); // 输出: 1 (二进制: 0001)

// 或(OR)操作
const orResult = a | b;

console.log(`${a} | ${b} = ${orResult}`); // 输出: 7 (二进制: 0111)

// 异或(XOR)操作
const xorResult = a ^ b;

console.log(`${a} ^ ${b} = ${xorResult}`); // 输出: 6 (二进制: 0110)

// 取反(NOT)操作
const notResult = ~a;

console.log(`~${a} = ${notResult}`); // 输出: -6 (二进制: 1010)

// 左移(Left Shift)操作
const leftShiftResult = a << 1;

console.log(`${a} << 1 = ${leftShiftResult}`); // 输出: 10 (二进制: 1010)

// 右移(Right Shift)操作
const rightShiftResult = a >> 1;

console.log(`${a} >> 1 = ${rightShiftResult}`); // 输出: 2 (二进制: 0010)

最终输出结果如下图所示:

通过学习 React 源码,使用位运算来实现权限管理,实在是太简单了 😉😉😉

在 React 中,它的 lane 模型里面的一些基本运算都封装成了一个函数,如下代码所示:

// 获取指定 Lanes 中的任意一个 Lane 的索引
function pickArbitraryLaneIndex(lanes: Lanes) {
  return 31 - clz32(lanes);
}

// 将单个 Lane 转换为其索引
function laneToIndex(lane: Lane) {
  return pickArbitraryLaneIndex(lane);
}

// 判断两个 lanes 集合之间是否有交集
export function includesSomeLane(a: Lanes | Lane, b: Lanes | Lane) {
  return (a & b) !== NoLanes;
}

// 判断两个 lanes 集合是否是父子集的关系
export function isSubsetOfLanes(set: Lanes, subset: Lanes | Lane) {
  return (set & subset) === subset;
}

// 合并两个 lanes 集合
export function mergeLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {
  return a | b;
}

// 从一个 lanes 集合中把某个 lane 或者 lanes 集合给移除掉,相当于求一个集合的补集
export function removeLanes(set: Lanes, subset: Lanes | Lane): Lanes {
  return set & ~subset;
}

// 求两个 lanes 集合的交集
export function intersectLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {
  return a & b;
}

这些函数主要用于管理和操作 Lanes 集合,通过位运算来实现高效的集合操作。位运算能够非常高效地处理集合的交集、并集、补集等操作,常用于需要快速处理和管理状态集合的场景,如调度任务。

如何基于位运算来实现权限操作

使用位运算来实现权限管理是一种高效且常见的方法。每个权限都可以表示为一个位(bit),通过位运算可以轻松地检查、添加、删除和组合权限。

  1. 定义权限:每个权限都对应一个位。

  2. 分配权限:使用位运算将多个权限组合在一起。

  3. 检查权限:使用位运算检查是否具备某个权限。

  4. 添加权限:使用位运算添加权限。

  5. 移除权限:使用位运算移除权限。

假设我们有如下的权限:

  1. 读取 (Read) 权限:位移表示:1 << 0,二进制表示:0b0001

  2. 写入 (Write) 权限:位移表示:1 << 1,二进制表示:0b0010

  3. 执行 (Execute) 权限:位移表示:1 << 2,二进制表示:0b0100

  4. 删除 (Delete) 权限:位移表示:1 << 3,二进制表示:0b1000

  5. 管理 (Admin) 权限:位移表示:1 << 4,二进制表示:0b10000

  6. 创建 (Create) 权限:位移表示:1 << 5,二进制表示:0b100000

  7. 查看 (View) 权限:位移表示:1 << 6,二进制表示:0b1000000

首先我们先定义这些权限

// 权限定义
const READ = 1 << 0; // 0b0001
const WRITE = 1 << 1; // 0b0010
const EXECUTE = 1 << 2; // 0b0100
const DELETE = 1 << 3; // 0b1000
const ADMIN = 1 << 4; // 0b10000
const CREATE = 1 << 5; // 0b100000
const VIEW = 1 << 6; // 0b1000000

// 将数字转换为二进制字符串并打印,添加 0b 前缀
const toBinaryString = (num, length = 8) =>
  "0b" + num.toString(2).padStart(length, "0");

console.log("二进制表示:");
console.log("读取 (READ):", toBinaryString(READ)); // 0b00000001
console.log("写入 (WRITE):", toBinaryString(WRITE)); // 0b00000010
console.log("执行 (EXECUTE):", toBinaryString(EXECUTE)); // 0b00000100
console.log("删除 (DELETE):", toBinaryString(DELETE)); // 0b00001000
console.log("管理 (ADMIN):", toBinaryString(ADMIN)); // 0b00010000
console.log("创建 (CREATE):", toBinaryString(CREATE)); // 0b00100000
console.log("查看 (VIEW):", toBinaryString(VIEW)); // 0b01000000

最终输出结果如下图所示:

通过学习 React 源码,使用位运算来实现权限管理,实在是太简单了 😉😉😉

通过一些基本操作,我们可以高效地管理和操作用户的权限,如下代码所示:

// 组合权限
let userPermissions = READ | WRITE | VIEW; // 组合权限,等于 0b01000011

// 检查权限函数
const hasPermission = (permissions, permission) =>
  (permissions & permission) !== 0;

console.log("\n初始权限:");
console.log("用户权限 (userPermissions):", toBinaryString(userPermissions)); // 0b01000011
console.log("读取 (Read):", hasPermission(userPermissions, READ)); // true
console.log("写入 (Write):", hasPermission(userPermissions, WRITE)); // true
console.log("执行 (Execute):", hasPermission(userPermissions, EXECUTE)); // false
console.log("删除 (Delete):", hasPermission(userPermissions, DELETE)); // false
console.log("管理 (Admin):", hasPermission(userPermissions, ADMIN)); // false
console.log("创建 (Create):", hasPermission(userPermissions, CREATE)); // false
console.log("查看 (View):", hasPermission(userPermissions, VIEW)); // true

// 添加权限函数
const addPermission = (permissions, permission) => permissions | permission;

// 移除权限函数
const removePermission = (permissions, permission) => permissions & ~permission;

// 添加执行权限
userPermissions = addPermission(userPermissions, EXECUTE);
console.log("\n添加执行权限后:");
console.log("用户权限 (userPermissions):", toBinaryString(userPermissions)); // 0b01000111
console.log("读取 (Read):", hasPermission(userPermissions, READ)); // true
console.log("写入 (Write):", hasPermission(userPermissions, WRITE)); // true
console.log("执行 (Execute):", hasPermission(userPermissions, EXECUTE)); // true
console.log("删除 (Delete):", hasPermission(userPermissions, DELETE)); // false
console.log("管理 (Admin):", hasPermission(userPermissions, ADMIN)); // false
console.log("创建 (Create):", hasPermission(userPermissions, CREATE)); // false
console.log("查看 (View):", hasPermission(userPermissions, VIEW)); // true

// 移除写入权限
userPermissions = removePermission(userPermissions, WRITE);
console.log("\n移除写入权限后:");
console.log("用户权限 (userPermissions):", toBinaryString(userPermissions)); // 0b01000101
console.log("读取 (Read):", hasPermission(userPermissions, READ)); // true
console.log("写入 (Write):", hasPermission(userPermissions, WRITE)); // false
console.log("执行 (Execute):", hasPermission(userPermissions, EXECUTE)); // true
console.log("删除 (Delete):", hasPermission(userPermissions, DELETE)); // false
console.log("管理 (Admin):", hasPermission(userPermissions, ADMIN)); // false
console.log("创建 (Create):", hasPermission(userPermissions, CREATE)); // false
console.log("查看 (View):", hasPermission(userPermissions, VIEW)); // true

最终输出结果如下图所示:

通过学习 React 源码,使用位运算来实现权限管理,实在是太简单了 😉😉😉

通过这种方式我们就可以便捷地管理我们项目中的权限了。

总结

位运算操作快速且占用内存少,容易理解和使用,可以灵活地组合、添加和移除权限,并且可以轻松扩展权限种类。但是前提是你需要对二进制这些内容有一定的理解。

转载自:https://juejin.cn/post/7394786709647278080
评论
请登录