核心是让回调函数轻量、短时、不抢主线程——单次执行别超50ms,避免同步忙等、dom重排、大对象操作;需拆分长任务、缓存不变值、避开高成本操作,并用web worker处理cpu密集型逻辑。

核心是让回调函数轻量、短时、不抢主线程——单次执行别超50ms,避免同步忙等、DOM重排、大对象操作。
拆分长任务,主动让出主线程
如果回调里要处理大量数据或复杂计算,别一口气干完。用 setTimeout(fn, 0) 或 requestIdleCallback 把任务切片,每次只处理一部分,留出空隙给浏览器响应用户操作。
- 比如遍历10万条记录做格式化:每次只处理1000条,然后 setTimeout 推下一轮
- 对用户不可见的后台聚合统计,优先用 requestIdleCallback,在浏览器空闲时慢慢跑
- 避免 while(Date.now() - start
缓存不变值,避免重复开销
回调每次触发都重新查 DOM、解析 JSON、创建正则、调用 Date.now()?这些都在浪费时间。
- DOM 元素提前 query 一次,存在变量里复用
- 正则表达式 /user-\d+/ 直接定义为常量,别在回调里 new RegExp
- 配置项从 localStorage 读一次就解析好,别每次回调都 JSON.parse
避开高成本操作,尤其是同步 I/O 和深拷贝
定时器回调里调 localStorage.setItem、JSON.stringify(巨量数据)、structuredClone 或频繁触发 offsetHeight/getBoundingClientRect,都会明显拖慢执行。
- 本地存储写入可批量攒几条再写,或改用 IndexedDB 异步处理
- 大对象转换尽量用浅拷贝(如 {...obj})或属性选择性提取,而非 structuredClone
- 需要测尺寸的,先缓存结果,别在每次回调里反复读
用 Web Worker 处理纯计算型逻辑
如果回调核心是加密、排序、图像处理这类 CPU 密集型任务,直接扔给 Web Worker,主线程只负责收结果。
- 主线程发数据:worker.postMessage({data: hugeArray, type: 'sort'})
- Worker 里算完再 postMessage 回来,不卡 UI
- 适合每秒执行但逻辑重的场景,比如实时音视频元数据解析











