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

时间:2010-11-12 11:56:45

标签: jquery dom memory memory-leaks

刚刚遇到了一个在Ajax webapp中遇到大量内存泄漏问题的客户。所以我决定创建以下测试用例来演示这个问题:

我在下面的示例中使用了drip / Sieve进行内存分析 (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作为List数据而不是我的静态内容obv的sympton相同。

我是否以错误的方式创建了DOM?任何人都可以告诉我为什么它不是垃圾收集,我看不到任何其他DOM元素的引用,为什么它们不应该被垃圾收集。另一个奇怪的行为是,当我点击空列表时(当调用jquery empty()方法时),有时候sIEve内存使用量会增加吗?

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

UPDATE,我尝试使用$('#listparent')。html(“”)而不是正确释放DOM,至少它是在sIEve中发布的。我想这是迄今为止最好的解决方案,虽然我没有解释为什么remove()和empty()似乎不起作用。也许它们只适用于静态添加的元素?

3 个答案:

答案 0 :(得分:1)

是的,你可以像sm so这样做一个巨大的进步

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次附加而不是10次附加。你总是需要在循环中避免DOM操作

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

答案 1 :(得分: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 :(得分:0)

$('#listparent').html(""); 

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

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

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