【问题标题】:Adding DOM elements with jquery append() appears to leak memory?使用 jquery append() 添加 DOM 元素似乎会泄漏内存?
【发布时间】:2011-05-09 00:55:57
【问题描述】:

刚遇到一位客户,他们的 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>

每次点击填充列表都会附加 10000 li 元素(表示为文本)。 Clearlist 调用 jquery empty() 应该清除 DOM 子树并使其符合 GC 条件。

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

这与我在使用 Jquery Ajax 获取列表数据而不是我的静态内容 obv 的客户处看到的相同。

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

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

更新,我尝试使用 $('#listparent').html("") 代替它似乎可以正确释放 DOM,至少它是在 sIEve 中释放的。我想这是迄今为止最好的解决方案,尽管我无法解释为什么 remove() 和 empty() 似乎不起作用。也许它们只适用于静态添加的元素?

【问题讨论】:

  • 只是好奇,你有没有在多个浏览器中试过这个?
  • No sIEve 只在 IE 下工作,没试过 FFX,主要是因为 IE 是本系统用户唯一使用的浏览器。
  • 其实 $('#listparent').html("");比 empty() 和 remove() 效果好得多,并且似乎释放了整个 DOM。我无语了

标签: jquery dom memory memory-leaks


【解决方案1】:

我建议附加到 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);

【讨论】:

    【解决方案2】:

    是的,你可以通过这样的方式取得巨大的进步

    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);
    
        }    
    ...
    

    尽可能少地限制 DOM 访问。

    不同之处在于您进行 1 次附加而不是 1 万次附加。你总是需要避免循环内的 DOM 操作

    编辑: 而不是 empty() 你的 ul 你有没有尝试删除() ul 然后突然重新创建它?

    【讨论】:

    • 这是一个很好的建议,我试过了,但问题仍然存在,它仍然在泄漏,并且 empty() 似乎没有释放 DOM。严重开始对 jquery 失去信心。
    • 我尝试了 remove(),它仍然泄漏,但可能比 empty() 略少,它似乎是在创建内存而不是释放。真正奇怪的是 $('#listparent').html("");诀窍并释放整个 DOM 和 RAM 内存?!?
    • @user408346 您介意用这些信息更新您的问题吗?另外,请将解决方案添加为答案,并尽可能将其标记为正确。它可能对许多人非常有用。
    【解决方案3】:
    $('#listparent').html(""); 
    

    在 empty() 或 remove() 都没有的地方工作。我希望我知道为什么。我想这是一个解决方案。

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

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

    【讨论】:

      猜你喜欢
      • 2012-02-20
      • 2021-10-01
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多