新闻详情

新闻详情

首页 / 资讯中心 / 详情

open-slide 性能优化指南:用 Set/Map 将 JavaScript 重复查找从 O(n) 降到 O(1)

发布时间:2026/9/29 4:27:37来源:尧图网络
open-slide 性能优化指南:用 Set/Map 将 JavaScript 重复查找从 O(n) 降到 O(1)
【免费下载链接】open-slideA slide framework built for agents.项目地址https://gitcode.com/gh_mirrors/op/open-slide点击查看免费下载本文是 open-slide 项目中 Vercel React Best Practices 技能集 中 JavaScript 性能优化规则js-set-map-lookups的深度展开。它解决的是前端/编辑器类应用中一个非常典型的问题在数组上反复执行includes、find等线性查找随着数据规模增长主线程计算量呈 O(n²) 级膨胀拖慢渲染与交互。读完本文你将掌握 Set/Map 的数据结构选型依据、正确的替换写法以及如何结合 open-slide 源码 中的真实案例如画布元素选取、文件夹索引、PPTX 导出图片映射落地这套优化。一、规则概览从 O(n) 到 O(1)原规则文件位于 .agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md属于 8 大分类中的JavaScript Performance影响等级 LOW-MEDIUM标注impactDescription: O(n) to O(1)。其核心主张只有一句话将数组转换为 Set/Map用于重复的成员资格检查membership checks。数组的includes、indexOf、find都是线性扫描——每检查一个元素就要从头遍历数组单次开销 O(n)。而Set.prototype.has与Map.prototype.get基于哈希表实现单次开销 O(1)平均情况下。当同样的检查在一个循环、一次渲染、或一个热路径函数里反复执行时二者的差距会被放大为 O(n × m) 与 O(n m)这就是本规则存在的意义。二、规则的原始示例错误的 O(n) 写法原规则给出的典型反例是白名单过滤const allowedIds [a, b, c, ...] items.filter(item allowedIds.includes(item.id))问题在于filter对items的每一项都会调用allowedIds.includes(item.id)而includes每次都是对整个allowedIds数组做一次线性遍历。设items有 N 项、allowedIds有 M 项总比较次数为N × M。当白名单与数据量同时增长到数百、上千级别主线程就会产生肉眼可见的卡顿——在 open-slide 这类需要实时响应拖拽、缩放、编辑操作的编辑器场景中尤其不可接受。三、正确的 O(1) 写法原规则的推荐写法是把数组一次性构造成Set把“扫描”变成“哈希命中”const allowedIds new Set([a, b, c, ...]) items.filter(item allowedIds.has(item.id))关键差异构建 Set 的成本new Set(array)只需一次 O(M) 的遍历且通常在循环之外执行每次检查的成本has是 O(1)于是整个过滤过程从 O(N × M) 降为O(N M)可读性allowedIds.has(item.id)语义上比allowedIds.includes(item.id)更明确地表达“这是集合成员判断”代码意图更清晰。补充一个 TypeScript 细节new Set([a, b, c, ...])会按字面量自动推断为Setstring当元素来自更宽泛的类型如string | undefined时可显式标注new Setstring(...)或在构造时用filter(Boolean)收窄避免has的参数类型告警。四、Set 与 Map 如何选择原规则标题同时提到了 Set 和 Map二者对应两种不同的使用场景场景数据结构关键方法适用问题只关心“是否存在”不需要关联数据SetThas/add/delete白名单过滤、去重、标签判定需要“按 key 取出关联数据”MapK, Vget/set/has建立 id → 对象的索引表选择原则很简单只需要成员判断就用 Set需要取回值就用 Map。二者在 open-slide 源码中都有大量印证见下一节。五、open-slide 源码中的真实实践这套规则并非纸上谈兵open-slide 的packages/core中可以看到多处一致的实现模式。1. 资源重名校验用 Set 做成员判断在 packages/core/src/app/lib/assets.ts 中生成新资源名时会构造当前已占用名称的集合const taken new Set(list.map((a) a.name));后续每一次“名称是否可用”的检查都走taken.has(name)避免了对资源列表反复线性扫描——这与原规则的白名单示例是同一个模式。2. 文件夹索引用 Map 做 id → 对象映射在 packages/core/src/app/lib/folders.ts 中通过map 二元组数组直接构造 Mapconst byId new Map(prev.folders.map((f) [f.id, f]));这正是原规则希望推广的“先建索引、再 O(1) 查询”范式new Map(entries.map(e [e.key, e]))一步到位。3. PPTX 导出图片 id 映射在 packages/core/src/app/lib/pptx/ooxml.ts 中导出 OOXML 时同样先建立图片索引const imageById new Map(deck.images.map((img) [img.id, img]));PPTX 导出需要按 id 反复引用图片关系用 Map 让每次引用都是 O(1) 命中而不是每次images.find(img img.id id)。4. 静态白名单集合标签判定open-slide 还用 Set 固化“静态枚举判定”例如 packages/core/src/app/lib/pptx/measure.ts 中的媒体标签集合、packages/core/src/app/components/inspector/inline-text-editor.tsx 中的行内样式键集合const RANGE_STYLE_KEYS new Set([fontSize, fontWeight, fontStyle, fontFamily, color]);对于这类“固定且频繁判定的枚举”模块级Set比数组includes更快也比switch分支更易扩展维护。5. 可视化编辑器的选区集合在 packages/core/src/app/lib/inspector/use-visual-editor.ts 中编辑选区相关逻辑使用new Set(targets.map(target target.anchor))收集目标元素——选中多个元素后要反复判定“某元素是否被选中”Set 的has使每次判定都是常数时间。从上述案例可以推断出本规则在 open-slide 中的典型适用面编辑器状态判定、资源/文件夹索引、导出管线中的对象映射、以及渲染循环内的白名单过滤。六、进阶变体一构建索引 Map 避免重复 find与js-set-map-lookups同属 JavaScript Performance 分类的 js-index-maps 规则 给出了它的“连招”当需要按同一 key 反复从数组中查找对象时不要写多个.find()而是先建一次 Map。错误写法每个订单都要线性查找一次用户function processOrders(orders: Order[], users: User[]) { return orders.map(order ({ ...order, user: users.find(u u.id order.userId) })) }正确写法先建索引查询全部 O(1)function processOrders(orders: Order[], users: User[]) { const userById new Map(users.map(u [u.id, u])) return orders.map(order ({ ...order, user: userById.get(order.userId) })) }该规则给出了一个直观的量化对比1000 个订单 × 1000 个用户朴素写法是 100 万次比较1M ops建索引后降到约 2000 次操作2K ops。open-slide 中 folders.ts 的byId与 ooxml.ts 的imageById正是这一变体的落地。七、进阶变体二模块级 Map 缓存重复函数调用再进一步js-cache-function-results 规则 展示了 Map 的另一种用法——模块级缓存当渲染期间同一函数被以相同输入反复调用时用模块级 Map 记住结果// Module-level cache const slugifyCache new Mapstring, string() function cachedSlugify(text: string): string { if (slugifyCache.has(text)) { return slugifyCache.get(text)! } const result slugify(text) slugifyCache.set(text, result) return result }该规则特别强调用 Map 而非 React Hook是因为它可以在工具函数、事件处理器等一切位置使用不局限于组件内部。这对 open-slide 这类“组件树之外还有大量 lib 逻辑”的代码库非常关键。八、注意事项与适用边界任何优化都有前提使用 Set/Map 时应留意以下几点只在“重复检查”时替换如果某数组只被查询一次includes与has的差距可以忽略引入 Set 反而多一次 O(n) 的构建成本。规则的适用前提是“repeated membership checks”。对象成员用引用相等Set.has与Map.get对对象使用引用比较SameValueZero若数组元素是每次新建的对象字面量集合可能永远“命中不了”。需要按字段比较时应先归一化 key如map(o o.id)。大数据集的构建时机Set/Map 的构建应放在循环与热路径之外如模块级或useMemo。例如 open-slide 在 asset-view.tsx 中使用useMemo(() new Set(assets.map(asset asset.name)), [assets])让依赖变化时才重建集合。内存与顺序Set/Map 保持插入顺序但不提供按值排序的语义若后续逻辑依赖原数组顺序可保留原数组仅在判断路径使用集合。九、小结js-set-map-lookups是一条小而实用的规则把数组includes换成Set.has、把find换成Map.get用一次 O(n) 的建表成本换取后续所有查询的 O(1)。它在 open-slide 中的价值不止于白名单过滤——从资源重名校验assets.ts、文件夹索引folders.ts、PPTX 图片映射ooxml.ts到可视化编辑器的选区判定use-visual-editor.ts全部遵循同一模式。配合 js-index-maps 与 js-cache-function-results 两条相邻规则你可以在渲染循环、导出管线与工具函数三个层面系统性地消除线性查找瓶颈。赞分享【免费下载链接】open-slideA slide framework built for agents.项目地址https://gitcode.com/gh_mirrors/op/open-slide点击查看免费下载相关推荐Phoenix 前端性能优化指南用 Set/Map 将 JavaScript 重复查找从 O(n) 降到 O(1)Phoenix 前端性能优化指南用 Set/Map 将 JavaScript 重复查找从 O n 降到 O 1 本指南源自当前仓库 .agents/skill可观测性AI 评测LLMOpsAI 应用人工智能Langfuse 前端性能优化用 Set/Map 将重复查找从 O(n) 降到 O(1)Langfuse 前端性能优化用 Set/Map 将重复查找从 O n 降到 O 1 本文基于 Langfuse 仓库内 web/.agents/skills人工智能LLMOps可观测性AI 评测LLM 网关后端前端Cherry Studio 性能优化实战用 Set/Map 将 JavaScript 成员查找从 O(n) 降到 O(1)Cherry Studio 性能优化实战用 Set/Map 将 JavaScript 成员查找从 O n 降到 O 1 本篇技术指南基于 Cherry StuAI 应用大模型桌面应用本地部署RAG创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

传感器端计算:把第一层智能塞进像素阵列,破解边缘AI功耗难题 2026/9/29 6:11:47

传感器端计算:把第一层智能塞进像素阵列,破解边缘AI功耗难题

传感器端计算(in-sensor computing)这两年在我的项目里出现的频率越来越高。之前做低功耗视觉识别时,最折磨人的不是模型选型,而是数据刚出像素阵列就已经把功耗和带宽吃掉大半,后端再强也只能干瞪眼。后来我把一部分卷…

阅读更多 →
DTFT与DFT本质区别:理论频谱与工程频谱的双重视角 2026/9/29 6:11:47

DTFT与DFT本质区别:理论频谱与工程频谱的双重视角

1. 这不是“背公式”的问题,而是信号世界里的两种“拍照方式”你翻过《数字信号处理》教材的傅里叶变换章节,大概率见过这样一幕:左边一页密密麻麻写着DTFT的积分式,右边一页又突然跳成DFT的求和式,中间连个过渡句都没…

阅读更多 →
2025软件测试面试高频题全解析:从基础理论到实战项目 2026/9/29 6:11:41

2025软件测试面试高频题全解析:从基础理论到实战项目

最近后台收到的私信里,高频出现同一个问题:“2025年软件测试面试到底还会不会问以前那些老题?八股文还有没有用?”我先说结论:面试题这东西,永远不会过时,但只看答案不思考背后的逻辑&#xff0…

阅读更多 →
Halcon 2D测量全解析:从边缘提取到亚像素拟合实战指南 2026/9/29 6:11:40

Halcon 2D测量全解析:从边缘提取到亚像素拟合实战指南

干机器视觉这些年,手里过的项目没有一百也有八十。从最早的螺丝外观检测,到后来的手机中框全尺寸测量,再到半导体封装的引脚共面度,兜兜转转发现最常用也最容易被低估的技术,还是Halcon这套老牌机器视觉库里的2D测量能…

阅读更多 →
基于SpringBoot框架的智慧养老平台设计与实现 2026/9/29 6:11:34

基于SpringBoot框架的智慧养老平台设计与实现

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 1. 项目背景与意义 随着我国人口老龄化进程不断加快,养老服务的供需矛盾日益突出。传统养老模式存在信息不对称、服务响应慢、管理效率低等问题,…

阅读更多 →
Apache Beam Runner 入门指南:理解执行引擎、--runner 参数与 DirectRunner 本地调试 2026/9/29 6:11:34

Apache Beam Runner 入门指南:理解执行引擎、--runner 参数与 DirectRunner 本地调试

大数据批处理流处理数据工程 【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址: https://gitcode.com/gh_mirrors/beam4/beam 点击查看 免费下载 本篇技术指南围绕 Apache Beam 的核心概念——…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉