内存泄漏及排查
javascript 是一门包含 GC(Garbage Collection) 的语言,用户无需手动释放内存,而是由 GC 来释放内存,但当由于某些原因(例如 BUG)导致 GC 无法正常的释放内存,此为内存泄漏
常见的内存泄漏
闭包不当
function factory() { const store = []; return function () { store.push(new Array(10000).fill(0)); };}const run = factory();
setInterval(run, 1000);全局变量
由于 window(global) 不会再程序执行中被 GC 回收,则挂载于 window(global) 的变量也不会被回收
window.store = [];function factory() { return function () { store.push(new Array(10000).fill(0)); };}const run = factory();
setInterval(run, 1000);DOM 未正确的回收
<body> <div id="parent"> <div id="children">123</div> </div></body>let parent = document.querySelector("#parent");let child = document.querySelector("#children ");
// 如果子元素被删除了setTimeout(() => { parent.removeChild(child); // child = null;}, 3000);- 打开 Chrome Dev Tools —> Memory(内存),记录下内存使用情况,称为记录 1
- 再删除子节,删除节点后,再去 Memory 中记录,称为记录 2
- 对比两次记录,在 Filter 中输入 detached,即可查看已脱离但未清除的对象
解决方式:因为是全局变量的原因,使得节点无法被回收,则将节点放入函数内部即可(使其变成局部变量)
控制台打印
console.log(不只是 console.log,还包含其他的例如 console.error、console.warn 等等)都会保存变量,如下代码所示
<body> <button id="button">点击我</button></body>
<script> const btn = document.querySelector("#button"); btn.addEventListener("click", () => { const obj = new Array(100000).fill(1); console.log(obj); // log 时,内存成猛然上升趋势,但是不log时,有明显的回收折线 });</script>句柄未关闭(定时器)
当定时器忘记清除(关闭)时,如果定时器内部使用的对象不会被回收,例如
const bigObj = new Array(1000000).fill(1);setInterval(function () { const obj = bigObj; // 定时器忘记被关闭了,则bigObj不会被回收}, 2000);