一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
内存泄漏:
内存泄漏(Memory Leak)
是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放
,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
如果内存不需要时,没有经过生命周期的释放期,那么就存在内存泄漏。
垃圾回收机制
Javascript 具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存
原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存
通常情况下有两种实现方式:
- 标记清除
- 引用计数
常见内存泄露情况
意外的全局变量
function foo(arg) {
bar = "this is a hidden global variable";
}
另一种意外的全局变量可能由 this
创建:
function foo() {
this.variable = "potential accidental global";
}
// foo 调用自己,this 指向了全局对象(window)
foo();
上述使用严格模式,可以避免意外的全局变量
定时器也常会造成内存泄露
var someResource = getData();
setInterval(function() {
var node = document.getElementById('Node');
if(node) {
// 处理 node 和 someResource
node.innerHTML = JSON.stringify(someResource));
}
}, 1000);
如果id
为Node的元素从DOM
中移除,该定时器仍会存在,同时,因为回调函数中包含对someResource
的引用,定时器外面的someResource
也不会被释放
不需要setInterval或者setTimeout时,定时器没有被clear,定时器的回调函数以及内部依赖的变量都不能被回收,造成内存泄漏。
clearTimeout(***)
clearInterval(***)
闭包造成内存泄露,维持函数内局部变量,使其得不到释放
解决方法: 不用的时候设为null
function bindEvent() {
var obj = document.createElement('XXX');
var unused = function () {
console.log(obj, '闭包内引用obj obj不会被释放');
};
obj = null; // 解决方法
}
没有清理对DOM
元素的引用同样造成内存泄露
const refA = document.getElementById('refA');
document.body.removeChild(refA); // dom删除了
console.log(refA, 'refA'); // 但是还存在引用能console出整个div 没有被回收
refA = null;
console.log(refA, 'refA'); // 解除引用
使用事件监听addEventListener
监听的时候,在不监听的情况下使用removeEventListener
取消对事件监听
例如mounted/created 钩子中使用 JS 绑定了 DOM/BOM 对象中的事件,需要在 beforeDestroy 中做对应解绑处理(vue)