使用jquery append()添加DOM元素似乎会泄漏内存?

使用jquery append()添加DOM元素似乎会泄漏内存?,jquery,dom,memory,memory-leaks,Jquery,Dom,Memory,Memory Leaks,刚刚会见了一位客户,他们的Ajax Web应用程序中存在大量内存泄漏问题。因此,我决定创建以下测试用例来演示该问题: 在下面的示例中,我使用了滴水/筛子进行内存分析 (http://home.orange.nl/jsrosman/) 情况很简单:我有以下javascript: <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.

刚刚会见了一位客户,他们的Ajax Web应用程序中存在大量内存泄漏问题。因此,我决定创建以下测试用例来演示该问题:

在下面的示例中,我使用了滴水/筛子进行内存分析 (http://home.orange.nl/jsrosman/)

情况很简单:我有以下javascript:

<html>
    <head>    
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js">
</script>    
</head>    
<script type="text/javascript">

    var lihtml = "<li class='green'>this is a test text</li>";

    function populatelist() {
        for (var i = 0; i < 10000; i++) {
            $('#listparent').append(lihtml);
        }    
    }    

    function clearlist() {
        $('#listparent').empty();
        if (typeof (CollectGarbage) == "function") {
            alert('gc');
            CollectGarbage();
        }    
    } 


    /* Alternative clearlist with Remove instead of Empty(), still leaks */
    function clearlist() {
        /* test remove the parent itself instead of empty below */
        $('#listparent').remove();
        $('body').append("<ul id='listparent'>");        
        //$('#listparent').empty();
        if (typeof (CollectGarbage) == "function") {
            alert('gc');
            CollectGarbage();
        }
    }

   /* Edit!, this is the most effective way to release memory so far */
   function clearlist() {
    $('#listparent').html("");
    if (typeof (CollectGarbage) == "function") {
        alert('gc');
        CollectGarbage();
    }
}
</html>   
</script>

<body>
    <button onclick="javascript:populatelist()">Populate list</button>
    <button onclick="javascript:clearlist()">Clear list</button>
    <ul id="listparent">
        <li>kjjk</li>
    </ul>    
</body>

</html>

var lihtml=“
  • 这是一个测试文本
  • ”; 函数populatelist(){ 对于(变量i=0;i<10000;i++){ $('#listparent').append(lihtml); } } 函数clearlist(){ $('#listparent').empty(); if(typeof(CollectGarbage)=“函数”){ 警报(“gc”); 收集垃圾(); } } /*带有Remove而不是Empty()的可选clearlist仍然泄漏*/ 函数clearlist(){ /*测试删除父级本身,而不是下面的空*/ $('#listparent')。删除(); $('body')。追加(); //$('#listparent').empty(); if(typeof(CollectGarbage)=“函数”){ 警报(“gc”); 收集垃圾(); } } /*编辑!,这是迄今为止释放内存最有效的方法*/ 函数clearlist(){ $('#listparent').html(“”); if(typeof(CollectGarbage)=“函数”){ 警报(“gc”); 收集垃圾(); } } 填充列表 清除列表
    • kjjk
    每次单击“填充列表”都会附加10000 li元素(以文本表示)。Clearlist调用jquery empty(),这应该清除DOM子树并使其符合GC的条件

    所以我在sIEve中运行这个例子,每次我添加新元素时,内存使用量都会增加,我从来没有看到过垃圾收集或释放内存。即使RAM使用量达到1.5GB,即使我尝试为IE显式调用GC,也不行

    这与我在客户那里看到的相同,客户使用jqueryajax来处理列表数据,而不是我的静态内容obv

    我是否以错误的方式创建DOM?有人能告诉我为什么它没有被垃圾收集吗?我看不到任何其他对DOM元素的引用,也看不到它们为什么不应该被垃圾收集。另一个奇怪的行为是,有时当我单击empty list(当调用jquery empty()方法时)时,内存使用量甚至会增加

    如果有人有意见,我会非常高兴


    更新时,我尝试使用$('#listparent').html(“”),它似乎正确地释放了DOM,至少它是在sIEve中释放的。我想这是目前为止最好的解决方案,尽管我没有解释为什么remove()和empty()似乎不起作用。也许它们只适用于静态添加的元素?

    是的,这样做可以大大改进smthg

    var lihtml = "<li class='green'>this is a test text</li>",
        listring = "";
    
    function populatelist() {
            for (var i = 0; i < 10000; i++) {
                listring += lihtml;
            }    
    
            $('#listparent').append(listring);
    
        }    
    ...
    
    var lihtml=“
  • 这是一个测试文本
  • ”, listring=“”; 函数populatelist(){ 对于(变量i=0;i<10000;i++){ listring+=lihtml; } $('#listparent')。追加(listring); } ...
    尽可能少地限制DOM访问

    不同之处在于,您只添加了1个附加,而不是1万个附加。您始终需要避免在循环内进行DOM操作

    编辑:
    您是否尝试过删除()ul,然后突然重新创建它?

    我建议附加到HTML字符串,然后将其添加到DOM:

    function populatelist() {
        for (var i = 0; i < 10000; i++) {
            //$('#listparent').append(lihtml);
            lihtml += "<li class='green'>this is a test text</li>";
        }    
    }    
    populateList();
    $('#listparent').append(lihtml);
    
    函数populatelist(){
    对于(变量i=0;i<10000;i++){
    //$('#listparent').append(lihtml);
    lihtml+=“
  • 这是一个测试文本
  • ”; } } 大众主义者(); $('#listparent').append(lihtml);
    在empty()和remove()都没有的情况下工作。我希望我知道为什么。我想这是一个解决办法

    /*这是迄今为止释放内存最有效的方法*/

    function clearlist() {
        $('#listparent').html("");
        if (typeof (CollectGarbage) == "function") {
            alert('gc');
            CollectGarbage();
        }
    

    这是一个很好的建议,我尝试过,但问题仍然存在,它仍然在泄漏,而且空()似乎无法释放DOM。我开始对jquery失去信心。我尝试了remove(),它仍然会泄漏,但可能比empty()稍少,empty()似乎会增加内存,而不是释放内存。真正奇怪的是$('#listparent').html(“”);这个技巧会释放整个DOM和RAM内存吗@用户408346您介意用这些信息更新您的问题吗?另外,请添加解决方案作为答案,如果可以,请将其标记为正确。它可能对很多人都很有用。只是好奇,你有没有在多个浏览器中尝试过这个功能?没有筛选只在IE中起作用,没有尝试FFX,主要是因为IE是这个系统中用户唯一使用的浏览器。实际上,$('#listparent').html(“”);比empty()和remove()都好得多,而且似乎可以释放整个DOM。我说不出话来
    function clearlist() {
        $('#listparent').html("");
        if (typeof (CollectGarbage) == "function") {
            alert('gc');
            CollectGarbage();
        }