内存泄漏和JS垃圾回收机制

内存泄漏(memory leak)

  • 程序的运行是需要分配内存空间的,如果一些不能用到的内存未及时释放无法释放,就会造成系统内存的浪费,导致浏览器卡顿甚至崩溃。
  • 为了防止内存泄漏,所以就需要垃圾回收机制及时释放用不到的内存。

JS垃圾回收机制原理

  • 标记清除:垃圾回收机制在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉处在环境中的变量及被环境中的变量引用的变量标记(闭包)。而在此之后剩下的带有标记的变量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后垃圾回收机制到下一个周期运行时,将释放这些变量的内存,回收它们所占用的空间。
  • 引用计数:垃圾回收器会定期扫描内存,如果一个值的引用次数是0,就表示这个值不再用到了,因此可以将这块内存释放。但如果两个变量互相引用时,他们的引用次数永远是2,就存在无法回收的问题。

常见的内存泄漏

  • 全局变量( 避免使用全局变量 )
num = 1;  
console.log( num );
num  = null;
  • 闭包
function f1() {
    var a = 1;
    function f2() {
        console.log(a++);
    };
    return f2
};
var f = f1();
f();
f = null;   //  f 和函数 f2 的联系被切断,f2 不再被引用,因此f2被回收
  • 定时器
let i = 0;
let  t = setInterval(function(){
    i++;
    if(i>3){
        clearInterval(t);
    }
    console.log(i);
},1000);
  • DOM 元素引用
let btn = document.getElementById('btn');
// ...
btn = null;
  • 监听在 window 的事件
window.addEventListener('click', this.fun);
// ...
window.removeEventListener('click', this.fun);

Vue 中容易出现内存泄露的几种情况

  • 清除全局变量
destroyed () {
    window.data = null; // 页面卸载的时候解除引用
}
  • 清除 EventBus 事件
destroyed () {
    EventBus.$off();
}
  • 清除监听在 window 的事件
beforeDestroy () {
  window.removeEventListener('click', this.fun);
}
  • 清除 Echarts 实例
beforeDestroy () {
  this.chart.clear();
}

ES6 防止内存泄漏

  • ES6 考虑到这点,推出了两种新的数据结构:weakset 和 weakmap 。
  • 他们对值的引用都是不计入垃圾回收机制的,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存。
const listener = new WeakMap();
const ele = document.getElementById('btn');
listener.set(ele, fun);
ele.addEventListener('click', listener.get(ele), false);

你可能感兴趣的:(内存泄漏和JS垃圾回收机制)