performanceobserver构造函数必须传入函数类型回调,否则抛typeerror;回调接收list和observer参数,需调用list.getentries()获取条目;observe前应检查type是否被supportedentrytypes支持;时间戳基于performance.timeorigin,需校准;必须手动disconnect()防止内存泄漏。

PerformanceObserver 构造函数必须传入回调函数
不传回调或传错类型(比如 undefined、null、字符串)会直接抛出 TypeError: Failed to construct 'PerformanceObserver': The callback provided must be a function。回调函数接收两个参数:第一个是 list(PerformanceObserverEntryList 实例),第二个是 observer(当前 PerformanceObserver 实例)。
实操建议:
- 回调中务必调用
list.getEntries()获取条目数组,不能直接遍历list - 回调内避免执行耗时操作,否则可能拖慢主线程,影响后续性能采集
- 推荐用箭头函数绑定上下文,避免
this丢失导致意外错误
observe() 方法的 type 必须是已注册的性能条目类型
常见可监听的 type 包括:"navigation"、"resource"、"paint"、"longtask"、"layout-shift" 等。但不是所有浏览器都支持全部类型——例如 "layout-shift" 在 Safari 中至今未实现,"longtask" 在部分旧版 Chrome 中需开启实验性 flag。
实操建议:
- 调用
observer.observe({ type: "xxx" })前,先检查该类型是否被支持:PerformanceObserver.supportedEntryTypes.includes("xxx") - 一个
PerformanceObserver实例可监听多个类型,用数组传入:{ type: ["navigation", "resource"] } - 不要在页面加载后太晚才调用
observe(),否则会错过早期条目(如navigation只触发一次,且在document.readyState === "loading"阶段就已生成)
监听到的条目时间戳是相对 performance.timeOrigin 的毫秒数
所有性能条目的 startTime 和 duration(如 PerformanceNavigationTiming、PerformanceResourceTiming)都是以 performance.timeOrigin 为基准的高精度时间戳,不是 Date.now()。这意味着跨页面或服务端对齐时间时,必须用 timeOrigin 校准,否则误差可达数十毫秒。
实操建议:
- 记录日志时,优先保存
entry.startTime+performance.timeOrigin得到绝对时间戳(毫秒级 Unix 时间) -
entry.duration对某些类型无意义(如navigation条目没有duration,只有各阶段时间点),使用前先console.log(entry)看结构 - 注意
timeOrigin在 cross-origin iframe 中可能不可读(返回0),此时无法还原绝对时间
必须手动 disconnect() 否则可能造成内存泄漏
PerformanceObserver 实例不会自动销毁,即使页面卸载,只要引用还存在,它就会持续接收新条目并触发回调。如果回调中闭包持有 DOM 节点或大对象,就容易引发内存泄漏——尤其在单页应用中反复创建 observer 却不清理。
实操建议:
- 在组件卸载、模块销毁或
beforeunload事件中显式调用observer.disconnect() - 避免全局变量直接存 observer,改用 WeakMap 或模块级 const + 显式生命周期管理
- 调试时可用
performance.getEntriesByType("navigation")辅助验证是否仍有未处理的条目堆积
timeOrigin 的校准逻辑和 disconnect() 的调用时机——这两处不出错时一切正常,一旦出错,问题往往延迟暴露、难以复现。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











