




JavaScript内存泄漏主因有四:全局变量意*载、事件监听器未解绑、闭包保留大对象或DOM引用、定时器未清除;需用严格模式、ESLint、AbortController、堆快照等工具定位并清理。
JavaScript 中未声明的变量会自动成为 window(浏览器)或 global(Node.js)的属性,长期持有对象引用就等于锁住内存。比如在函数里写 user = { name: 'Alice' } 而不是 let user = { name: 'Alice' },这个对象就永远活在全局作用域里。
let/const/var 的赋值语句'use strict'),让这类错误直接报 ReferenceError
no-implicit-globals 或 no-unused-vars 提前拦截给元素绑定 addEventListener 后,如果组件卸载、页面跳转或 DOM 被移除,但没调用 removeEventListener,回调函数及其闭包捕获的变量就会持续驻留内存。React/Vue 等框架内部处理了部分情况,但手动操作 DOM 时极易遗漏。
const handler = () => {...}; el.addEventListener('click', handler); el.removeEventListener('click', handler);
AbortContro
ller 配合 addEventListener 的 signal 选项(现代浏览器支持),销毁时调用 controller.abort() 即可批量清理EventEmitter),确保订阅者在生命周期结束时调用 off 或 removeListener
闭包本身不是问题,但当内部函数被意外保留在长生命周期对象(如定时器、全局缓存、未清除的 Promise 回调)中,并捕获了大型数据结构或 DOM 元素,就会阻止垃圾回收。
document.body;改用 ID 或轻量标识符,需要时再查Memory > Take heap snapshot 对比前后快照,筛选 Closure 类型,看哪些变量名下挂了不该有的 DOM 或大型对象setInterval / setTimeout)setInterval 是最典型的“隐形内存锚点”:只要定时器 ID 还有效,其回调函数和闭包内所有变量就无法被回收,哪怕对应的 UI 已经消失。常见于轮询接口、动画帧控制、状态同步等场景。
const timerId = setInterval(...)),并在合适时机调用 clearInterval(timerId)
visibilitychange)、或数据流终止时主动清理,不要依赖用户关闭标签页setInterval 却不先 clearInterval —— 这会产生多个并行定时器,且旧的仍活着