<html>
<head>
<script language="javascript">
var arr = new Array();
function c()
{
    var div = document.createElement("DIV");
    document.body.appendChild(div);
    div.innerHTML = '<input type="button" value="从内部删除" onclick="f()"/><div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div>';
    arr.push(div);
    abcd.innerText = arr.length;
}function f()
{
    var tmp = arr.pop();
    while(tmp!=null)
    {
        document.body.removeChild(tmp);
tmp.childNodes[1].style.filter = "";//发现style的filter是个特殊的东西 需要手动释放一下
        tmp = arr.pop();
    }
    abcd.innerText = arr.length;
this.onclick = null;
}function g()
{
    CollectGarbage();
}</script>
</head>
<body><input type="button" value="添加" onclick="c();" />
<input type="button" value="删除" onclick="f();" />
<input onclick="g()" type="button" value="释放内存" />
<div id="abcd"></div>
典型的 半透明层 内存泄露问题:<br />
测试:(必须在IE下测试才能发现问题)<br />
1、依次执行“添加”“删除”“释放内存”,如此反复多次,发现内存可以正常释放。<br />
2、依次执行“添加”“从内部删除”“释放内存”,如此反复多次,发现内存泄露无限制增长。
</body>
</html>

解决方案 »

  1.   

    方法1:
    对于remove的对象来说,它还是存在的,可以append回来:<html>
    <head>
    <script language="javascript">
    var arr = new Array();
    var currentNum=0;
    function c()
    {
    if(arr[currentNum]) document.body.appendChild(arr[currentNum]);
    else{
         var div = document.createElement("DIV");
         document.body.appendChild(div);
         div.innerHTML = '<input type="button" value="从内部删除" onclick="f()"/><div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div>';
         arr.push(div);
        }
        currentNum++;
        abcd.innerText = currentNum;
    }function f()
    {
        for (var i=currentNum-1;i>-1;i--)
        {
            document.body.removeChild(arr[i]);
        }
        currentNum=0;
        abcd.innerText = currentNum;
    }function g()
    {
        CollectGarbage();
    }</script>
    </head>
    <body><input type="button" value="添加" onclick="c();" />
    <input type="button" value="删除" onclick="f();" />
    <input onclick="g()" type="button" value="释放内存" />
    <div id="abcd"></div>
    典型的 半透明层 内存泄露问题:<br />
    测试:(必须在IE下测试才能发现问题)<br />
    1、依次执行“添加”“删除”“释放内存”,如此反复多次,发现内存可以正常释放。<br />
    2、依次执行“添加”“从内部删除”“释放内存”,如此反复多次,发现内存泄露无限制增长。
    </body>
    </html>
      

  2.   

    if(fCkBrs()===1)onunload = function(){fFixMl();};
      function fFixMl(oEle)
      { // shawl.qiu code, void return
       if(!oEle)oEle=document.body;
       var atr=oEle.attributes;
       if(atr)
        for(var i=0, j=atr.length; i<j; i++)
         if(typeof oEle[atr[i].name]=='function')oEle[atr[i].name]=null;
       if(oEle.childNodes)
        for(var i=0, j=oEle.childNodes.length; i<j; i++)
         arguments.callee(oEle.childNodes[i]);
      } // end function fFixMl(oEle)
      function fCkBrs()
      {// shawl.qiu script, return integer
       switch (navigator.appName)
       {
        case 'Opera': return 2;
        case 'Netscape': return 3;
        default: return 1;
       }
      } // end function fCkBrs 
      

  3.   

    我是楼主:经过几天的调试分析,初步得出一种猜测,仅供大家参考,只是猜测,千万别被我误导:
    点击“从内部删除”按钮的时候,所以造成了资源相互引用,所以CollectGarbage()认为资源仍然被占用,所以不去释放资源。
    备注:因为是在IE上发现的这个问题,火狐下没有发现类似情况,所以我准备给微软写信,大家支持我一下,有了新的进展我会及时贴到这个帖子后面。希望大家继续讨论问题。
      

  4.   

    也可以用innerHTML删除:<html>
    <head>
    <script language="javascript">
    var currentNum=0;
    function c()
    {
        var div = document.createElement("DIV");
        document.getElementById("aaaaa").appendChild(div);
        div.innerHTML = '<input type="button" value="从内部删除" onclick="f()"/><div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div>';
        currentNum++;
        abcd.innerText = currentNum;
    }function f()
    {
        document.getElementById("aaaaa").innerHTML="";
        currentNum=0;
        abcd.innerText = currentNum;
    }function g()
    {
        CollectGarbage();
    }</script>
    </head>
    <body><input type="button" value="添加" onclick="c();" />
    <input type="button" value="删除" onclick="f();" />
    <input onclick="g()" type="button" value="释放内存" />
    <div id="abcd"></div>
    典型的 半透明层 内存泄露问题:<br />
    测试:(必须在IE下测试才能发现问题)<br />
    1、依次执行“添加”“删除”“释放内存”,如此反复多次,发现内存可以正常释放。<br />
    2、依次执行“添加”“从内部删除”“释放内存”,如此反复多次,发现内存泄露无限制增长。
    <div id="aaaaa">
    </div>
    </body>
    </html>
      

  5.   

    我又测试了一下发现还是onclick事件的问题 
    只要在卸载将onclick事件置空就可以完全释放内存了
    我测试添加20次 删除 再添加20次 内存都是98M左右 而且不用使用CollectGarbage()方法function f()
    {
        var tmp = arr.pop();
        while(tmp!=null)
        {
            document.body.removeChild(tmp);
    tmp.onclick = null;//onclick事件也最好置空一下
            tmp = arr.pop();
        }
        abcd.innerText = arr.length;
    }
      

  6.   

    都是一些事件搞的, 这问题你不用给MS写信了, N早有N多人知道了...
      

  7.   

    另外你可以去看看我以前的帖子
    http://topic.csdn.net/u/20070501/09/eeb7bb7b-ebe9-432d-a496-87a645e75cfd.html
      

  8.   

    回复1楼:(gzdiablo)
    我把你贴的代码原样测试了一下,发现问题依旧。
      

  9.   

    回复3楼(JK_10000)
    removeChild 之后我又调用了 CollectGarbage(); 所以内存应该得到释放了,因为点击“删除”按钮(参考测试1)后就可以正常释放内存。
      

  10.   

    回复4楼(btbtd )
    不好意思,小弟才疏学浅,没看明白兄弟写的什么意思。麻烦哪位朋友给讲解一下
      

  11.   

    回复6楼(JK_10000)
    和你之前描述的情况一样,我测试了一下,只要与arr脱离了关系又removeChild了,应该可以正常释放了,因为没有了任何引用,即使这个内存不释放也不能再次使用了,所以调用CollectGarbage(); 应该正常释放的。另外,参考我之前说过的理由:
    removeChild   之后我又调用了   CollectGarbage();   所以内存应该得到释放了,因为点击“删除”按钮(参考测试1)后就可以正常释放内存。
      

  12.   

    月の影 11:45:30
    js和DOM对象占用的内存很多
    IE下createElement的DOM对象无论如何应当挂到documentElement之下的节点中去
    否内进程里的内存白丢
    别指望被回收月の影 12:07:11
    所以最好不要临时生成 不用的DOM对象月の影 12:07:48
    我不知道为什么,只能理解为
    对于进程来说DOM对象申请的资源是永久的
      

  13.   

    IE下createElement的DOM对象无论如何应当挂到documentElement之下的节点中去 
    否内进程里的内存白丢 
    别指望被回收 
    即使挂上去了,也不会被回收只是不挂,心理不平衡:D
      

  14.   

    回复第7楼(gzdiablo):
    按照你所讲的,设置了tmp.onclick = null;
    我测试了,结果问题仍然没有改变。
      

  15.   

    To: DBXP 
    ----
    楼主的出发点:确认这是个IE的bug,可以向IE报告。
    JK的出发点:碰到IE的bug,只能当作是踩到了便便,绕过就成。---另:给IE报bug的古道热肠值得鼓励.
      

  16.   

    补充:回复第7楼(gzdiablo): 
    连续点开20个层然后一起关闭,最后释放内存,这样确实可以释放一些内存,但是反复几次发现内存会持续上涨。
    如果你打开一个关闭一个立即释放内存,反复重复上述过程,就会发现内存几乎没有一点释放的
      

  17.   

    给大家个提醒:
    大家测试的时候,观察windows 任务管理器的 “PF使用”,而不是“进程”选项卡。
      

  18.   

    IE 会释放的 但不是立刻 可能要等一会 
    加20个层时内存测试开始PF:806MB
    第一次 98.224k
    第二次 98.444k
    3: 98.544k
    4: 98.676k
    5: 98.680k
    6: 98.752k
    7: 98.748k
    8: 98.752k
    9: 98.628k
    10: 98.752k
    11: 98.756k
    12: 98.752k
    13: 98.748k
    14: 98.684k
    15: 98.764k
    16: 98.768k
    17: 98.784k
    18: 98.768k
    19: 98.716k
    20: 98.716k20次之后PF:807MB
      

  19.   

    回22楼:gzdiablo
    你的怎么涨的这么慢?我的每添加一个层PF就增加4M
    我使用的是IE6
      

  20.   

    回复4楼:btbtd
    我看明白你的代码了,增加你的代码后,内存依然没有被释放掉
      

  21.   

    经JK前辈指点<script type="text/javascript">
    var arr = [];
    function c() {
        document.body.innerHTML += '<div id="tdiv_'+ arr.length + '">'
    + '<div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div>'
    + '</div>';
    arr[arr.length] = "tdiv_" + arr.length;
    }function f() {
        while(tmp = arr.pop()) {
    tmp = document.getElementById(tmp);
    if (tmp.outerHTML) tmp.outerHTML = "";
    else tmp.parentNode.removeChild(tmp);
    }
    }
    </script>
    <input type="button" value="添加" onclick="c();" />
    <input type="button" value="删除" onclick="f();" />
      

  22.   

    我的也是IE6 测试没问题.
    而且内存也没涨 最终稳定在98,7XX左右
    没使用CollectGarbage();
    说明大部份内存已经被释放了 可能有部分其他变量没有被释放而已.
    问题已经很明了了 如果没有别的问题 我也就此结束回复了.
      

  23.   


    这样问题貌似解决了...流程: 添加 -> 从内部删除 -> 释放内存...
    <html>
    <head>
    <script language="javascript">
    var arr = new Array();
    function c()
    {
        var div = document.createElement("DIV");
        var Main = document.getElementById("Main");
        document.body.appendChild(div);
        div.innerHTML = '<input type="button" value="从内部删除" onclick="f();"/><div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div>';
        arr.push(div);
        abcd.innerText = arr.length;
    }function f()
    {
        var tmp = arr.pop();
        while(tmp!=null)
        {
    //        for(var i = tmp.childNodes.count-1; i >=0 ; i--)
    //        {
    //            tmp.removeChild(tmp.childNodes[i]);
    //        }
            document.body.removeChild(tmp);
            tmp = arr.pop();
        }
            abcd.innerText = arr.length;
       fFixMl();
    }function g()
    {
     fFixMl();
    }    function   fFixMl(oEle) 
        {   //   shawl.qiu   code,   void   return 
          if(!oEle)oEle=document.body; 
          var   atr=oEle.attributes; 
          if(atr) 
            for(var   i=0,   j=atr.length;   i <j;   i++) 
              if(typeof   oEle[atr[i].name]== 'function ')oEle[atr[i].name]=null; 
          if(oEle.childNodes) 
            for(var   i=0,   j=oEle.childNodes.length;   i <j;   i++) 
              arguments.callee(oEle.childNodes[i]); 
        }   //   end   function   fFixMl(oEle) 
        function   fCkBrs() 
        {//   shawl.qiu   script,   return   integer 
          switch   (navigator.appName) 
          { 
            case   'Opera ':   return   2; 
            case   'Netscape ':   return   3; 
            default:   return   1; 
          } 
        }   //   end   function   fCkBrs  
    </script>
    </head>
    <body><input type="button" value="添加" onclick="c();" />
    <input type="button" value="删除" onclick="f();" />
    <input onclick="g()" type="button" value="释放内存" />
    <div id="Main">
    <div id="abcd"></div>
    典型的 半透明层 内存泄露问题:<br />
    测试:(必须在IE下测试才能发现问题)<br />
    1、依次执行“添加”“删除”“释放内存”,如此反复多次,发现内存可以正常释放。<br />
    2、依次执行“添加”“从内部删除”“释放内存”,如此反复多次,发现内存泄露无限制增长。
    </div>
    </body>
    </html>
      

  24.   

    应该是先把创建的 Element 删除后, 才可以真正释放内存, 
      

  25.   

    两个消息,悲喜各参一半:
    第一个是坏消息,我的电脑中木马了,刚刚才恢复好,上来看看帖子,回头再次进行了测试,奇怪的是有了新的发现,就是主帖子上说的那段代码有了新的情况,具体情况看下面的例子。
    第二个消息是好消息,27楼(btbtd)兄弟的代码通过测试,内存释放很快。详细测试结果:执行此行代码“fFixMl();”能够更快的释放内存,大概从第2或3次开始就会即时释放内存。如果不执行此行代码,大概需要消耗70M左右才会释放内存(注意:不是之前的不释放情况了,不知道是否与系统重做(插件什么的都没有了)有关系)。<html>
    <head>
    <script language="javascript">
    var arr = new Array();
    function c()

        var div = document.createElement("DIV"); 
        document.body.appendChild(div); 
        div.innerHTML = '<input type="button" value="从内部删除" onclick="f()"/><div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div>';
        arr.push(div); 
        abcd.innerText = arr.length; 
    } function f() 

        var tmp = arr.pop(); 
        while(tmp!=null) 
        { 
    //        for(var i = tmp.childNodes.length-1; i >= 0 ; i--) 
    //        { 
    //            tmp.removeChild(tmp.childNodes[i]); 
    //        } 
            document.body.removeChild(tmp); 
            tmp = arr.pop(); 
        } 
            abcd.innerText = arr.length; 
            fFixMl();//我的测试结果:执行此行代码能够更快的释放内存。如果不执行此行代码,大概需要消耗70M左右才会释放内存。否则大概从第2或3次开始就会即时释放内存。
    } function g() 

        fFixMl();
    } function fFixMl(oEle) 
    {   //   shawl.qiu   code,   void   return 
        if(!oEle)
        {
            oEle=document.body;
        }
        var atr=oEle.attributes;
        if(atr)
        {
            for(var i=0, j=atr.length; i<j; i++)
            {
                if(typeof(oEle[atr[i].name])=='function') ;//oEle[atr[i].name]=null;
            }
        }
        if(oEle.childNodes)
        {
            for(var i=0, j=oEle.childNodes.length; i<j; i++)
            {
                arguments.callee(oEle.childNodes[i]);
            }
        }
    }   //   end   function   fFixMl(oEle) 
    </script>
    </head>
    <body><input type="button" value="添加" onclick="c();" />
    <input type="button" value="删除" onclick="f();" />
    <input onclick="g()" type="button" value="释放内存" />
    <div id="abcd"></div>
    典型的 半透明层 内存泄露问题:<br />
    测试:(必须在IE下测试才能发现问题)<br />
    1、依次执行“添加”“删除”“释放内存”,如此反复多次,发现内存可以正常释放。<br />
    2、依次执行“添加”“从内部删除”“释放内存”,如此反复多次,发现内存泄露无限制增长。
    </body>
    </html>
      

  26.   

    其实IE是有内置的内存释放模式的 只要你将相应的引用设置为null IE就会在适当的时候去对其重新分配
    但HTML元素内的function成员是个例外 如果你不手动设置成null 就算卸载了这个HTML元素 IE也不会去主动释放它 包括function内引用到的所有内存都不会被释放btbtd的方法确实是个万全之策,不过效率比较低.毕竟要遍历所有HTML节点的所有属性.
    建议LZ如果是你自己写的程序 最好手动的去卸载这些function 好像你上面的程序 只要加个onclick=null就行了
      

  27.   

    btbtd
    同学,这个方法你可以测试下
    把卸载属性那个去掉也会释放内存的(大多情况)我很好奇啊它明明只是跑了一遍,就把内存给释放了?由于跑的时候帮助浏览器检测到了垃圾?(很可能的说)
    另外
    这个问题,根本就和function的释放没有直接关系你可以把那个按钮去掉也不会释放的
    主要的原因是filter,不过实在不理解跑一变为什么就可以释放。还有。。即使不跑的话JK前辈说到。用innerHTML就可以释放。。并且我测试用outerHTML也可以释放。并且很效率
      

  28.   

    呵呵, 君不见有 oEle 参数,
    只要指定一个容器, document.getElementById(x) 就可以专项专对
      

  29.   

    始终要遍历element的全部成员 效率本来就差了.
    ie下单个元素的成员就多达120多.遍历一次的时间消耗不是小数何况还要判断成员的类型.
      

  30.   

    一般情况下给某个HTML元素附加的方法都是在事件柄上的 所以只要你在开发的时候稍微留意 就可以轻松的卸载他们.
    当然在使用各种UI框架时却会遇到各种情况,好像ext和yahooUI都没有专门的针对对象的内存卸载方法. 对付这种情况最好的就是用btbtd的通用方法完成释放工作.
      

  31.   

    没想到这篇帖子引来这众多高手。最近新发现,似乎腾迅那个QQZone有问题(目前我还没找到卸载QQZone的方法,无法考证是否腾迅惹的祸,请遇到和我同样问题的朋友也帮忙留意一下这个问题)。我的电脑中毒了(之前我有讲到),重新恢复系统后发现即时不用调用任何明确的释放方法(包括btbtd给出的代码)也可以正确释放内存,只不过明确指定释放后会更及时。之后一直到安装了QQZone更新就再次出现了本帖子我讲的那种内存无法正确释放的情况。我会一直留意这个问题,并把最新的问题发现回复到此帖。
      

  32.   

    对于利用innerHTML属性附加上去的元素在删除之前付空值就可以了,如果是用createElement附加的元素就用removeChild.
    因此你的那个稍微改一下就不会出现内存泄露了,也不需要调用CollectGarbage方法
        while(typeof tmp != 'undefined')
        {
    tmp.innerHTML = "";
            document.body.removeChild(tmp);
            tmp = arr.pop();
        }
      

  33.   

    用 document.createElement() 创建的对象都会在内存里存在一个引用,并且这个引用是不会被释放的,所以一般这种大量的HTML注入操作推荐你使用另一个方法
    insertAdjacentHTML!<html>
    <head>
    <script language="javascript">if(typeof(HTMLElement)!="undefined" && !window.opera)
    {
      HTMLElement.prototype.insertAdjacentHTML=function(where, html)
      {
        var e=this.ownerDocument.createRange();
        e.setStartBefore(this);
        e=e.createContextualFragment(html);
        this.insertAdjacentElement(where,e);
      };
      HTMLElement.prototype.insertAdjacentElement=function(where, e)
      {
        switch (where)
        {
          case 'beforeBegin': this.parentNode.insertBefore(e, this);break;
          case 'afterBegin': this.insertBefore(e, this.firstChild); break;
          case 'beforeEnd': this.appendChild(e); break;
          case 'afterEnd':
            if(!this.nextSibling) this.parentNode.appendChild(e);
            else this.parentNode.insertBefore(e, this.nextSibling); break;
        }
      };
    };
    var arr = new Array();
    function c()
    {
        var id = "mm_"+ (new Date().getTime().toString(36));
        document.getElementById("mm").insertAdjacentHTML("beforeEnd", '<div id="'+ id +'"><input type="button" value="从内部删除" onclick="f()"/><div style="position:absolute;top:110;left:110;width:1000px;height:1000px;-moz-opacity:0.07;filter:alpha(opacity=7);background-color:#000000"></div></div>')
        arr[arr.length] = document.getElementById(id);
        abcd.innerHTML = arr.length;
    }function f()
    {
      arr.length = 0;
      document.getElementById("mm").innerHTML = "";
    }function g()
    {
        CollectGarbage();
    }</script>
    </head>
    <body><input type="button" value="添加" onclick="c();" />
    <input type="button" value="删除" onclick="f();" />
    <input onclick="g()" type="button" value="释放内存" />
    <div id="abcd"></div>
    典型的 半透明层 内存泄露问题:<br />
    测试:(必须在IE下测试才能发现问题)<br />
    1、依次执行“添加”“删除”“释放内存”,如此反复多次,发现内存可以正常释放。<br />
    2、依次执行“添加”“从内部删除”“释放内存”,如此反复多次,发现内存泄露无限制增长。
    <div id="mm"></div>
    </body>
    </html>
      

  34.   

    insertAdjacentHTML 存在兼容问题...
      

  35.   

    如获至宝偶加上翻译,转到偶blog里去(有空在转:D)HTMLElement.prototype.insertAdjacentHTML = function(where, html) {
    //Meizz
    var e = this.ownerDocument.createRange();
    e.setStartBefore(this);
    e = e.createContextualFragment(html);
    this.insertAdjacentElement(where, e);
    };

    HTMLElement.prototype.insertAdjacentElement = function(where, e) {
    //Meizz
    switch (where) {
    case 'beforeBegin' : this.parentNode.insertBefore(e, this); break;
    case 'afterBegin' : this.insertBefore(e, this.firstChild); break;
    case 'beforeEnd' : this.appendChild(e); break;
    case 'afterEnd' : 
    if (!this.nextSibling) this.parentNode.appendChild(e);
    else this.parentNode.insertBefore(e, this.nextSibling);
    break;
    }
    };
      

  36.   

    哦, 俺看到一长串的代码一般不看...
    你那个树能不能修修, 用Opera 9+ 根本看不了导航, 
      

  37.   

    ext里面出现过类似的insertAdjacentHTML的代码
    btbtd最好研究一下各个js框架 很有帮助的
    还有FF提供了大量的对象原型供开发者扩展 真的很方便.
      

  38.   

    哦, 研究...你没开玩笑吧, 
    现在各个浏览器有什么东西基本上我可以倒背出来...
    系统化的东西, 我现在可以一个人写个CMS系统...
      

  39.   

    不好意思搞错人了 应该是叫muxrwc去研究一下
      

  40.   

    回41楼(meizz)你说的方法确实可以释放内存,但是却多使用了一个<div id="mm"></div>标签,感觉不是很爽,而且当我们需要动态生成的时候不一定能够提前预知有这样一个标签。