单页应用组件销毁时须主动清理内存泄漏源。需成对清除事件监听器(使用同一函数引用和options实例)、优先用AbortController批量清理、同步清除全局监听、定时器、闭包及DOM引用。

单页应用中组件销毁时若不主动清理,很容易留下内存“幽灵”——DOM节点、事件监听器、定时器、闭包引用都可能继续驻留,拖慢页面甚至引发崩溃。关键不是等垃圾回收,而是提前切断所有引用链。
确保事件监听器成对清除
绑定和解绑必须使用**同一个函数引用**和**同一个 options 实例**,否则 removeEventListener 无效:
- 避免匿名函数或箭头函数绑定:每次调用都会生成新函数,无法匹配移除
- 正确做法是声明具名函数或变量:const handleClick = () => { ... }; 然后统一用于 addEventListener 和 removeEventListener
- 带选项(如 { capture: true })时,必须复用同一对象实例,不能每次都新建一个
优先用 AbortController 批量清理
现代浏览器(Chrome/Firefox/Safari 15.4+)支持 signal 选项,一行 controller.abort() 即可清空所有关联监听:
- 绑定时传入 { signal: controller.signal }
- 组件卸载时调用 controller.abort(),无需保存 handler 引用,也不怕闭包滞留
- 天然适配框架生命周期:React 的 useEffect 清理函数、Vue 3 的 onBeforeUnmount、Web Component 的 disconnectedCallback
别漏掉全局与委托监听
绑在 document、window 或滚动容器上的监听器,不会随组件 DOM 消失而自动释放:
立即学习“Java免费学习笔记(深入)”;
- React:在 useEffect 返回函数中执行 controller.abort() 或显式 removeEventListener
- Vue 3:推荐用 onBeforeUnmount(比 onUnmounted 更早,DOM 尚在,操作更安全)
- Vue 2:用 beforeDestroy(destroyed 阶段 DOM 可能已不可访问)
同步清理定时器、闭包与 DOM 引用
除了事件监听,这几类资源同样需要手动干预:
- 定时器:保存 setInterval/setTimeout 返回的 id,在卸载时调用 clearInterval(id) 或 clearTimeout(id)
- 闭包:避免长期持有大对象;必要时将闭包变量设为 null,切断引用
- DOM 引用:组件移除后,若 JS 中仍保留 let el = document.getElementById(...) 这类引用,需主动赋值为 null


















