JavaScript内存泄漏是因引用未断开致GC无法回收,主要类型包括:①意外全局变量,②未清除事件监听器,③闭包持有大对象或DOM引用,④未释放定时器和DOM引用;核心原则是“谁创建引用,谁负责断开”。

JavaScript内存泄漏,指的是本该被自动回收的内存,因为某些引用未断开,导致垃圾回收器(GC)无法释放它,内存占用持续增长,最终可能拖慢甚至卡死页面。
意外的全局变量
函数里漏写let/const/var,变量会悄悄挂到window上,长期驻留。比如this在非严格模式下调用时指向window,也可能意外创建全局属性。
- 开头加"use strict",让漏声明直接报错
- 避免直接往window塞数据,真要用就设为null及时清理
- 检查控制台是否出现ReferenceError以外的隐式全局变量警告
未清除的事件监听器
DOM元素被移除后,如果还留着addEventListener绑定的回调,整个回调函数及其闭包里的变量都动不了——尤其当回调里引用了大数组、图片或组件实例时,泄漏更明显。
- 动态添加的监听器,务必配套调用removeEventListener
- 优先用{ once: true },适合只触发一次的场景
- 在组件卸载钩子中统一解绑(如React的useEffect返回函数、Vue的beforeUnmount)
闭包持有大对象或DOM引用
闭包会让外部变量“活”得比预期久。比如一个计数器闭包里存了10MB的ArrayBuffer,哪怕业务早不用了,只要闭包还在,这块内存就一直占着。
立即学习“Java免费学习笔记(深入)”;
- 避免在闭包中缓存大型数据或DOM节点,改用WeakMap存弱引用
- 用完后主动把引用变量设为null,帮GC识别“可回收”
- 谨慎使用私有变量模式,确认生命周期与实际使用匹配
定时器和未释放的DOM引用
setInterval没清,回调函数和它用到的所有变量就永远在线;DOM节点从页面删了,但JS里还有const el = document.getElementById(...),那这个节点连带它的样式、事件、子节点全卡在内存里。
- 所有定时器ID(setInterval/setTimeout)都要配对clearInterval/clearTimeout
- 移除DOM前,先解绑事件、清空数据引用,再设el = null
- 避免长期缓存大量DOM节点,按需查,用完即弃
基本上就这些。核心就一条:谁创建的引用,谁负责断开。保持对变量生命周期的敏感,比等内存爆了再查更省力。











