示例:setInterval 或 setTimeout 未及时用 clearInterval/clearTimeout 清除。
后果:定时器持续运行,其回调函数中引用的外部变量无法释放。
框架场景:在 React 的 useEffect 中启动定时器但未在清理函数中清除。
示例:给 DOM 元素添加事件监听(如 addEventListener),但在元素销毁时未调用 removeEventListener。
后果:被监听元素若被移除,但事件回调仍被持有,导致元素无法回收。
框架场景:Vue 组件的 beforeDestroy 生命周期中未移除事件监听。
示例:未使用 var/let/const 声明变量,或显式绑定到 window(如 window.data = ...)。
后果:全局变量始终可达,垃圾回收器不会回收。
注意:模块化开发可减少此类问题,但需警惕 this 的意外指向(如函数内非严格模式下的 this 指向 window)。
示例:函数返回一个内部函数,且该函数被长期引用(如作为事件回调),导致外层函数的作用域链无法释放。
后果:闭包引用的外部变量会持续占用内存。
优化:在不再需要时手动解除引用(如将回调设为 null)。
示例:JS 中保留了对已移除 DOM 元素的引用(如 const element = document.getElementById('x'); element.remove())。
后果:DOM 元素虽不在文档树中,但被 JS 变量引用,无法被回收。
解决:在移除 DOM 后,主动将变量设为 null。
示例:使用 Map 或对象缓存数据,但未设置清理策略(如 LRU 算法)。
后果:缓存数据持续累积,占用内存。
优化:设置缓存上限或过期时间,定期清理无用数据。
示例:旧版 jQuery 插件可能在元素移除后保留引用;React 组件卸载后未取消网络请求或事件订阅。
后果:关联资源无法释放。
解决:遵循框架生命周期,在卸载时手动清理(如 React 的 useEffect 清理函数)。
示例:使用 Map 或 WeakMap 存储对象时,若用 Map 且未手动删除键,键对象无法释放。
区别:WeakMap 的键是弱引用,不会阻止垃圾回收。
检测工具:Chrome DevTools 的 Memory 面板(Heap Snapshots、Allocation Timeline)、Performance 面板监控内存趋势。
预防措施:
避免全局变量,使用严格模式('use strict')。
及时清除定时器、事件监听、异步回调。
在框架生命周期中清理资源(如 React 的 useEffect 返回清理函数)。
谨慎使用闭包,及时解除引用。
使用弱引用(WeakMap/WeakSet)替代强引用。
前端内存泄漏的核心是无用资源仍被引用,导致无法被垃圾回收。熟悉常见场景(如定时器、事件、闭包等),结合开发框架的生命周期管理,能有效避免此类问题。定期通过工具检测内存变化,是保障应用性能的关键。