核心是保障主线程响应性:将长任务拆分为5–10ms小块并yield,重逻辑移至web worker;高频事件加节流/passive;用事件委托和weakmap优化监听与状态管理;避免微任务堆积影响渲染。

核心是不让主线程被长时间占用,确保事件循环能及时处理用户输入和渲染任务。低端机尤其敏感,16ms 一帧的窗口稍一超时,滚动就卡、点击就没反馈。
把长任务切成小块,主动让出主线程
一段同步执行 100ms 的遍历或计算,会连续霸占主线程,页面直接“假死”。这不是代码写错了,而是没给事件循环留出调度空间。
- 用 setTimeout 或 queueMicrotask 拆分:每次只处理 100–200 条数据,然后 yield 一次
- 控制单块耗时在 5–10ms 内,这样每帧至少能腾出空隙响应点击或触发重绘
- 对 JSON 解析、模板渲染等重逻辑,优先移到 Web Worker 中执行,主线程零负担
高频事件必须加节流和 passive 标志
滚动、触摸在低端机上每秒可触发上百次。不加约束,回调会瞬间堆满调用栈,后续所有任务都得排队等。
- scroll/touchmove 监听务必带上 {passive: true},浏览器跳过 JS 判断,直接滑动,流畅度立升
- 真需要监听滚动位置变化,用 requestAnimationFrame 节流,比 setTimeout 更贴合帧率节奏
- 搜索框输入这类场景,用 防抖(debounce) 延迟执行,避免每敲一个字就触发请求或重绘
精简监听器,减少内存与调度开销
每个 addEventListener 都要分配对象、绑定作用域,大量监听器不仅拖慢初始化,还会干扰垃圾回收。
- 动态列表项(如商品卡片)别逐个绑 click,统一用 事件委托 绑在父容器上
- 组件卸载时,一定调用 removeEventListener,尤其注意闭包中 handler 引用未清除导致的内存泄漏
- 需要存 DOM 元素关联状态时,用 WeakMap,元素被移除后状态自动释放,减轻 GC 压力
小心微任务堆积,别让 Promise 抢光渲染时间
Promise.then、MutationObserver 是微任务,会在当前宏任务结束后立刻批量执行。链太深或触发太密,下一帧的渲染就被挤没了。
- 避免在 for 循环里连续 new Promise 或链式 .then
- MutationObserver 的监听范围尽量收窄,比如只监听 class 变化,而不是 subtree 全量
- 非紧急任务可考虑 requestIdleCallback,让浏览器在空闲帧里执行,不影响用户交互
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











