Skip to content

内存泄漏及排查

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);
  1. 打开 Chrome Dev Tools —> Memory(内存),记录下内存使用情况,称为记录 1
  2. 再删除子节,删除节点后,再去 Memory 中记录,称为记录 2
  3. 对比两次记录,在 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);