美文网首页
常见javascript 中内存泄漏的几种情况

常见javascript 中内存泄漏的几种情况

作者: 幸宇 | 来源:发表于2021-03-22 21:55 被阅读0次

    1、什么是内存泄漏?
    在程序中,由于疏忽或者错误,造成程序内存被占用而一直没有被释放从而失去控制,从而造成内存的浪费

    2、垃圾回收机制
    我的理解:在javascript中是有负责自动管理内存的机制的东西,我们称这种管理叫做垃圾回收机制管理,而且垃圾回收机制管理是自动进行的,是不可见的,我们平时所创建的基本类型、对象、函数...所有这些都需要内存,而这些内存的自动化管理和释放都需要 垃圾回收来管理。

    所以垃圾回收机制它会管理哪些条件的内存呢?总的来就是那些 不可访问 的对象,进行回收释放;说不可访问,我们可以去理解以下可以访问的对象具有的特点就是:可达,比如:
    1、一些基本的固有值,显而易见的
    全局变量、函数内部变量和参数、调用其他函数的变量或参数,这些都是可达的,js引擎不会自动释放这些内存;
    2、相互引用的对象之间,比如:
    局部对象引用其他对象,那么该对象和其引用对象都是可达的。

    3、垃圾回收机制常见策略
    1、标记清除:比较常用的策略,它是指:在变量标记为“离开环境”时,被清除释放,当变量进入环境时标记为“进入环境”,在标记为“进入环境”时,不能释放内存,因为随时都有可能用到。例如:

    var m = 0,n = 19  // 把 m,n,add() 标记为进入环境。
    add(m, n)           // 把 a, b, c标记为进入环境。
    console.log(n)   // a,b,c标记为离开环境,等待垃圾回收。
    function add(a, b) {
      a++
      var c = a + b
      return c
    }
    

    上述代码中,调用函数add,里面局部变量c,参数a,b在标记为进入环境时,不能释放,console.log(n)执行后,a,b,c 标记为离开环境,可以回收,但m,n变量不可以释放;

    2、引用计数:在js引擎中有一张引用表,保存所有资源的引用次数,如果引用次数是0,表示该值不再引用,则可以释放内存,如果引用次数不为0,那么垃圾回收机制不会释放内存,从而导致内存泄漏,比如:

    const arr = [1, 2, 3, 4];
    console.log('hello world');
    

    代码中数组[1,2,3,4]是一个值,会占用内存,变量 arr是引用了这个值,因此引用次数为1,尽管后面没有再用到,它仍然可以通过arr找到值,会持续占用内存,也遵循可达性,将会持续占用内存,如果想要回收,则 arr=null,就可以释放;

    综上所述,垃圾回收机制虽然会自动释放一些内存空间,但并不代表内存不会泄漏,所以有些变量不再用到,需要检查是否存在对不再用到变量的引用,如果存在,需要手动释放;

    常见内存泄漏情况
    1、意外使用全局变量,比如函数内部使用全局变量:

    function foo(arg) {
        bar = "this is a hidden global variable";
    }
    或者:
    function foo2(){
    this.varable = "hello"
    }
    foo2();//调用后,this指向window全局变量
    

    2、定时器,定时器不清除,一直占用内存,得不到释放,或者在定时器内调用外部函数,得不到释放;
    3、闭包,内部函数引用外部函数变量,得不到释放,比如:

    function bindEvent() {
      var obj = document.createElement('XXX');
      var unused = function () {
        console.log(obj, '闭包内引用obj obj不会被释放');
      };
      obj = null; // 解决方法
    }
    

    4、不清理dom元素的引用,比如:

    const refA = document.getElementById('refA');
    document.body.removeChild(refA); // dom删除了
    console.log(refA, 'refA'); // 但是还存在引用能console出整个div 没有被回收
    refA = null;
    console.log(refA, 'refA'); // 解除引用
    

    5、监听事件的解除,监听的时候addEventListener,在不监听的时候要使用remveEventListener;

    相关文章

      网友评论

          本文标题:常见javascript 中内存泄漏的几种情况

          本文链接:https://www.haomeiwen.com/subject/nfzmcltx.html