zoukankan      html  css  js  c++  java
  • javascript常见内存泄露

    一、全局变量引起的内存泄漏

    function func(){
      lmw = 123456 //lmw是全局变量,不会被释放   
    }
    

     二、闭包引起的内存泄漏

    function func(){
      var lmw = 123456;//闭包环境,不会被释放
      function lmw2(){
        //就算是一个空函数,也不会释放
      }
      return lmw2 //被暴露在外界,随时可能被引用
    }
    

     三、子元素存在引用引起的内存泄漏

    var select = document.querySelector;
    var treeRef = select('#tree');
    
    var leafRef = select('#leaf');   //在COM树中leafRef是treeFre的一个子结点
    
    select('body').removeChild(treeRef);//#tree不能被回收入,因为treeRef还在

    解决方法:

    treeRef = null;//tree还不能被回收,因为叶子结果leafRef还在
    leafRef = null;//现在#tree可以被释放了

    四、定时器泄露

    var  timer=null
    for(var  i=0;i<5;i++){
        var funcObj = {
            "handle":function(){
                var _this = this;
                timer = setTimeout(function(){
                    console.log(_this)
                    _this.handle()
                },9000)
            }
        }
    }
    funcObj.handle()
    funcObj = null //只是改变funcObj存储在栈里的引用地址,堆里保存的真实对象不会被释放,定时器还在引用
    console.log(funcObj)

    真正的释放还要清除定时器,再把funcObj = null

    clearTimeout(timer)
    funcObj = null
    console.log(funcObj)

    五、循环引用

    function fn() {
     var a = {};
     var b = {};
     a.pro = b;
     b.pro = a;
    }
     
    fn();
    以上代码a和b的引用次数都是2,fn()执行完毕后,两个对象都已经离开环境,在标记清除方式下是没有问题的,但是在引用计数策略下,因为a和b的引用次数不为0,所以不会被垃圾回收器回收内存,如果fn函数被大量调用,就会造成内存泄露。在IE7与IE8上,内存直线上升。
    IE中有一部分对象并不是原生js对象。比如,DOM和BOM中的对象就是使用C++以COM对象的形式实现的,而COM对象的垃圾回收机制采用的就是引用计数策略。因此,即使IE的js引擎采用标记清除策略来实现,但js访问的COM对象依然是基于引用计数策略的。
    换句话说,只要在老IE中涉及COM对象,就会存在循环引用的问题
    var element = document.getElementById("some_element");
    var myObject = new Object();
    myObject.e = element;
    element.o = myObject;
    
    
    这个例子在一个DOM元素(element)与一个原生js对象(myObject)之间创建了循环引用。其中,变量myObject有一个名为e的属性指向element对象;而变量element也有一个属性名为o回指myObject。由于存在这个循环引用,即使例子中的DOM从页面中移除,它也永远不会被回收。
    解决方法:
    myObject.e= null;
    element.o = null;
    再来看一个在日常开发中容易犯错的例子:
    window.onload=function outerFunction(){
     var obj = document.getElementById("element");
     obj.onclick=function innerFunction(){};
    };
    这段代码看起来没什么问题,但是obj引用了document.getElementById(“element”),而document.getElementById(“element”)的onclick方法会引用外部环境中的变量,自然也包括obj。
    解决方法:
    window.onload=function outerFunction(){
     var obj = document.getElementById("element");
     obj.onclick=function innerFunction(){};
     obj=null;
    };
    
    
    将变量设置为null意味着切断变量与它此前引用的值之间的连接。当垃圾回收器下次运行时,就会删除这些值并回收它们占用的内存。
    在上面描述的循环引用例子,还可以理解成闭包循环引用导致的内存泄漏
    当对DOM元素进行其他操作时,仍然要处处留心。只要是将JavaScript对象指定给DOM元素,就可能在旧版本IE中导致内存泄漏。jQuery只是有助于减少发生这种情况的可能性

    注意:IE9+并不存在循环引用导致Dom内存泄露问题

     
  • 相关阅读:
    Redis知识梳理(1)当我们谈到双写一致性的时候,我们在谈什么?
    多线程知识梳理(4),当我们谈到volatile的时候,我们在谈什么?
    多线程知识梳理(3),当我们谈到CAS的时候,我们在谈什么?
    多线程知识梳理(2),当我们谈到synchronized关键字的时候,我们在谈什么?
    多线程知识梳理(1):当我们谈到指令乱序的时候,在谈什么?
    LeetCode刷题记录本
    “退格”转义字符使用实例
    “逻辑异或”进行数值交换的过程分析
    ConcurrentHashMap源码走读
    Netty如何监控内存泄露
  • 原文地址:https://www.cnblogs.com/liumingwang/p/6769774.html
Copyright © 2011-2022 走看看