javascript卡顿本质是主线程被长任务或高频小任务持续占用。用performance面板抓取≥50ms长任务,关注main轨道色块、tasks筛选、call tree排序;用performanceobserver监听运行时长任务;高频短任务需节流/防抖、passive优化;避免layout thrashing,读写分离,优先使用transform/opacity。

JavaScript 执行过长引起的卡顿,本质是主线程被单个任务或密集小任务持续占用,导致浏览器无法及时响应用户输入、更新动画或渲染帧。排查核心不是猜,而是用工具看清“谁在占着线程不放”。
用 Performance 面板直接抓出长任务
打开 Chrome DevTools → Performance 标签 → 点击录制(●),复现卡顿操作(如点击、滚动、加载)→ 停止录制。重点关注:
- Main 轨道:找宽度 ≥50ms 的连续色块(默认黄色/红色),鼠标悬停可看耗时、函数名、源码行号
- Summary 面板 → Tasks 分类:筛选 Duration > 50ms 的条目,点击可跳转到对应时间点
-
Call Tree 或 Bottom-up 标签:按 Total Time 排序,快速定位耗时最高的函数(比如未节流的
resize回调、同步 DOM 遍历、大量getBoundingClientRect()调用)
用 PerformanceObserver 主动监听长任务
在页面早期注入以下代码,可捕获运行时所有超 50ms 的任务,方便日志归因或上报:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.warn('Long Task detected:', {
duration: entry.duration,
startTime: entry.startTime,
name: entry.name // 通常是 'self' 或触发该任务的事件类型
});
}
});
observer.observe({ entryTypes: ['longtask'] });
注意:该 API 只能捕获主线程上真正超过阈值的任务,不包含微任务或异步回调内部的子耗时。
检查是否是“伪长任务”——高频短任务挤压
有时没有单个 >50ms 的任务,但页面仍卡顿。这往往是因为高频事件(如 scroll、input、mousemove)每秒触发几十次,每次执行 10–20ms,连续压满事件循环。此时 Performance 面板中会看到 Main 轨道上密密麻麻的小黄块,中间几乎没有空隙。
- 在 Events 轨道确认事件触发频率
- 检查对应监听器是否做了计算、DOM 读写、样式修改等重操作
- 用
passive: true优化滚动监听(避免阻止默认行为) - 对非关键逻辑加节流(
throttle)或防抖(debounce)
结合代码上下文判断是否强制同步布局
如果调用栈里频繁出现 getBoundingClientRect、offsetTop、clientWidth 等属性,且后面紧跟样式修改(如 el.style.color = 'red'),大概率发生了 Layout Thrashing(回流风暴)。
- 所有读操作集中放在前面,所有写操作集中放在后面
- 改用
transform、opacity等只触发改写层(composite)的属性 - 用
document.createDocumentFragment()批量插入节点,减少重排次数
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











