用 Map 存储权限标识可将菜单过滤从 O(n) 降至 O(1),初始化转为 Map 或 Set,使用 has 方法快速判断;支持嵌套权限、Symbol 键防冲突、动态增删高效、递归过滤性能稳定。

用 Map 存储权限标识并做存在性检查,能直接把菜单过滤从 O(n) 降为 O(1),避免每次遍历整个权限数组或反复调用 includes。
用 Map 替代数组或 Object 存权限标识
后端返回的权限列表通常是字符串数组,比如 ['menu:user', 'menu:role', 'action:delete']。如果每次判断菜单是否显示都用 permissions.includes('menu:user'),那每渲染一个菜单项都要线性扫描一次——10 个菜单就是 10 次 O(n) 查找,数据一多就卡顿。
- ✅ 正确做法:初始化时转成
new Map(permissions.map(p => [p, true]))或更轻量的new Set(permissions)(仅需存在判断) - ✅ 使用时:直接
permissionMap.has('menu:user'),引擎底层哈希查找,稳定常数时间 - ⚠️ 注意:别用
{}对象模拟,obj['menu:user']虽快但易受原型污染;且无法区分undefined是未授权还是值本就是undefined
菜单配置中嵌套权限键,用 Map 支持多级判断
有些菜单需要组合权限,比如“编辑用户”要同时有 menu:user 和 action:edit;或者按角色分组,如 role:admin → ['menu:log', 'menu:config']。这时单层 Map 不够用,可以:
- ✅ 用 Map 套 Map:
const rolePermissionMap = new Map([['admin', new Set(['menu:log', 'menu:config'])]]),查起来仍是两级 O(1) - ✅ 键用 Symbol 避免字符串冲突:
const MENU_USER = Symbol('menu:user'); permissionMap.set(MENU_USER, true),语义清晰又防覆盖 - ✅ 若菜单项本身带权限字段(如
{ label: '用户管理', permission: 'menu:user' }),可直接permissionMap.has(item.permission),一行决定显隐
动态更新权限时,Map 的增删不破环性能稳定性
用户切换角色、临时开通某项功能时,权限会实时变化。Object 扩展属性或频繁改 length 易触发隐藏类失效;而 Map 的 set/delete 是专为高频变更设计的:
立即学习“Java免费学习笔记(深入)”;
- ✅ 新增权限:
permissionMap.set('menu:report', true),不影响已有项查找速度 - ✅ 撤回权限:
permissionMap.delete('menu:report'),比从数组里splice或filter快得多 - ✅ 结合响应式框架(如 Vue 的 reactive 或 React 的 useState),只需更新 Map 实例,依赖它的菜单组件自动重渲染,无额外 diff 开销
配合菜单树结构做递归过滤时,Map 让每一层判断都高效
真实菜单是树形结构,需递归过滤并保留父路径。若每层都用数组 includes,时间复杂度会变成 O(depth × n),极易卡死。换成 Map 后:
- ✅ 递归函数内每次调用
has都是 O(1),整棵树过滤退化为 O(m),m 是节点总数 - ✅ 示例逻辑:
function filterMenu(node) { const matched = permissionMap.has(node.permission); const children = node.children?.map(filterMenu).filter(Boolean) || []; return matched || children.length ? { ...node, children } : null; } - ✅ 进阶:把菜单 ID 也存进 Map(
menuMap.set(node.id, node)),后续做展开/选中状态管理时也能快速定位


















