JS内存泄漏如何检测?场景哪些?

144 阅读2分钟

如何判断内存泄漏?内存发生变化?如何检测内存变化?

const arr = [];
for(let i=0;i<10*10000;i++){
    arr.push(i);
}
function bind(){
  //模拟一个比较大的数据
  const obj = {
      str: JSON.stringify(arr);
  }
  window.addEventListener('resize',()=>{
      console.log(obj);
  })
}

let n = 0;
function start(){
    setTimeout(()=>{
        bind();
        n++;
        //执行50次
        if(n<50){
            start();
        }else{
        alert('done')
        }
    
    },200);
}

document.getElementById('btn').addEventListener('click',()=>{
    start();
});

在页面memory中看内存变化 检测内存变化

  • 如果内存泄漏,会一直上升
  • 检测工具:wangEditor检测内存泄漏

内存泄漏场景有哪些呢?(Vue为例)

  • 被全局变量、函数引用,组件销毁时未清除
  • 被全局事件、定时器引用,组件销毁时未清除
  • 被自定义事件引用,组件销毁时未清除
data(){
    return {
        arr:[10,20,30],
        intervalId: 0
    }
},
methods(){
    window.arr = this.arr;//全局变量、函数引用
    printArr(){
        console.log(this.arr);
    }
},
mount(){
   //会导致内存泄漏
    window.addEventListener('resize',this.printArr)
    //定时器使用,会发生内存泄漏
    setInterval(()=>{
        console.log(this.arr);
    },100);
},
//页面销毁前,清空数据
beforeUnmount(){
    window.arr = null;
    window.printArr = null;
    if(this.intervalId){
        clearInterval(this.intervalId);
    }
    window.removeEventListener('resize',this.printArr);
}

重点

  • 前几年前端不太注重内存泄漏,因为不像后端7*24持续运行
  • 近几年前端功能不断复杂,内存问题也要重点考虑

拓展:WeakMap WeakSet(弱引用)

我们常用的对象Object,是由key:value集合组成的,但key只能是字符串,有很大的使用限制。当我们需要其他类型的数据做key值时,就需要用到数据结构Map,它支持把各种类型的值,当做键。

var map = new Map();
var zhang = {name:'张三'};
var li = {name:'李四'};
map.set(zhang,zhangsan);
map.set(li,lisi);
console.log(map.get(zhang));    //{name:'zhangsan'}
console.log(map.get(li));    //{name:'lisi'}

除了通过set还可以通过new Map添加成员变量

weakMap与map的区别:

  1. WeakMap只接受对象作为key,如果设置其他类型的数据作为key,会报错。
  2. WeakMap的key所引用的对象都是弱引用,只要对象的其他引用被删除,垃圾回收机制就会释放该对象占用的内存,从而避免内存泄漏。
  3. 由于WeakMap的成员随时可能被垃圾回收机制回收,成员的数量不稳定,所以没有size属性。
  4. 没有clear()方法
  5. 不能遍历