用 Set 实现权限交集的核心是初始化阶段统一转为 Set 实例,避免每次运算重复转换;通过遍历小集合调用 has() 实现高效交集;必要时用 WeakMap 缓存固定组合结果。

用 Set 实现权限列表交集,核心是利用其 O(1) 查找性能 和原生 has() 方法,避免数组嵌套循环的 O(n×m) 开销。关键不在“怎么写”,而在“怎么组织数据”和“何时转换”。
权限数据统一转为 Set 实例
不要在每次求交时才转数组为 Set —— 那会重复消耗。初始化阶段就把用户权限、角色权限、接口白名单等,全部存为 Set:
- 用户 A 的权限:
new Set(['read:user', 'edit:post', 'delete:comment']) - 某接口所需权限:
new Set(['read:user', 'edit:post']) - 角色 B 的权限:
new Set(['read:user', 'read:post', 'export:data'])
后续所有交集运算都基于 Set,不碰原始数组。
手动遍历小集合做交集(推荐)
Set 没有内置交集方法,但用 for...of 遍历较小集合 + has() 判断,效率最高:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function intersect(setA, setB) {
const result = new Set();
const [smaller, larger] = setA.size <= setB.size ? [setA, setB] : [setB, setA];
for (const item of smaller) {
if (larger.has(item)) result.add(item);
}
return result;
}
这样时间复杂度是 O(min(m, n)),比双层循环快得多。实际场景中,接口所需权限通常远少于用户总权限,所以“小集合”往往是权限规则侧。
交集结果可直接用于鉴权判断
不需要把交集转回数组——Set 本身就能高效判断是否满足最低权限:
- 检查是否至少拥有某几个权限:
[...requiredPerms].every(p => userSet.has(p)) - 检查交集非空(即有重叠权限):
intersect(userSet, routePerms).size > 0 - 获取具体匹配项(如用于日志或调试):
Array.from(intersect(userSet, routePerms))
避免无意义的 Array.from() 或展开操作,除非业务明确需要数组形态。
配合 WeakMap 缓存高频交集结果
对固定组合(如“管理员角色 + 订单页权限”)可缓存结果,减少重复计算:
const intersectionCache = new WeakMap();
function getCachedIntersect(setA, setB) {
const key = setA; // 假设 setA 是稳定引用(如角色 Set)
if (!intersectionCache.has(key)) {
intersectionCache.set(key, intersect(setA, setB));
}
return intersectionCache.get(key);
}
注意:WeakMap 要求键是对象引用,适合缓存角色/模块等长期存在的 Set;用户权限动态变化则不宜缓存。

















