javascript中的内存泄漏,循环中的函数

时间:2018-01-24 11:48:16

标签: javascript jquery ajax memory memory-leaks

我循环了一个来自ajax响应的响应,响应是一个包含1000个对象的数组,这个响应用于创建一个1000行的html表:

第一种情况:

    for (var i in msg.myObjects) {
    $('#mytablebody').append('<tr><td>' + msg.myObjects['item1'] + '</td><td>' + 
msg.myObjects['item2'] + '</td><td>' + msg.myObjects['item3'] + '</td><td>' + 
msg.myObjects['item4'] + '</td><td>' + msg.myObjects['item5'] + '</td><td>' + 
msg.myObjects['item6'] + '</td><td>' + msg.myObjects['item7'] + '</td> .... </tr>');
    }

结果=&gt;内存泄漏我的RAM转到了2Go,我的浏览器崩溃了

第二种情况:

    for (var i in msg.myObjects) {
        document.getElementById('mytablebody').innerHTML = document.getElementById('mytablebody').innerHTML + '<tr><td>' + 
msg.myObjects['item1'] + '</td><td>' + 
    msg.myObjects['item2'] + '</td><td>' + msg.myObjects['item3'] + '</td><td>' + 
    msg.myObjects['item4'] + '</td><td>' + msg.myObjects['item5'] + '</td><td>' + 
    msg.myObjects['item6'] + '</td><td>' + msg.myObjects['item7'] + '</td> .... </tr>';
        }

结果=&gt;内存泄漏我的RAM达到800Mo,我的浏览器崩溃了第二次ajax调用

第三种情况:

var stringResponse = '';
        for (var i in msg.myObjects) {
            stringResponse += '<tr><td>' + msg.myObjects['item1'] + '</td><td>' + 
        msg.myObjects['item2'] + '</td><td>' + msg.myObjects['item3'] + '</td><td>' + 
        msg.myObjects['item4'] + '</td><td>' + msg.myObjects['item5'] + '</td><td>' + 
        msg.myObjects['item6'] + '</td><td>' + msg.myObjects['item7'] + '</td> .... </tr>';
            }
document.getElementById('mytablebody').innerHTML = stringResponse 

结果=&gt;没有内存泄漏

好的,直到这里我得出结论,首先,.append()会导致内存泄漏,其次,你不应该在循环中使用DOM元素。但是当我做第四个场景时,我得出结论,第一个结论是错误(不完全正确),第二个结论仍然是正确的。

第4种情况:

    var stringResponse = '';
            for (var i in msg.myObjects) {
                stringResponse += '<tr><td>' + replaceNulls(msg.myObjects['item1']) + '</td><td>' + 
            msg.myObjects['item2'] + '</td><td>' + msg.myObjects['item3'] + '</td><td>' + 
            msg.myObjects['item4'] + '</td><td>' + msg.myObjects['item5'] + '</td><td>' + 
            msg.myObjects['item6'] + '</td><td>' + msg.myObjects['item7'] + '</td> .... </tr>';
                }
    document.getElementById('mytablebody').innerHTML = stringResponse 

function replaceNulls(input) {
  return input != null ? input : ''
}

结果=&gt;内存泄漏我的RAM转到了2Go,我的浏览器崩溃了

我的问题是:

当我们调用在循环外发生的函数时,它可能会导致内存泄漏,为什么?

如何避免这种情况(不删除函数或将处理移到循环内)?

1 个答案:

答案 0 :(得分:2)

现代Web浏览器的1000个表条目不应该导致任何问题。

在这里,我将10,000个项目添加到没有ram问题的表中。 它之所以快,是因为我在一个独立的DOM元素中构建了列表,然后在完成后附加。

您的问题可能仅限于DOM绘制问题,浏览器必须重新绘制所有更新。

我注意到的另一件事,for (var i in msg.myObjects)取决于你的msg.myObjects包含的内容,这不是一件好事。如果你可以使用现代JS, for (const i of msg.myObjects)更好。

&#13;
&#13;
var table = document.querySelector("table");

var tbody = document.createElement("tbody");

function addLine (txt) {
  var tr = document.createElement("tr");
  var td = document.createElement("td");
  tr.appendChild(td);
  td.innerText = txt;
  tbody.appendChild(tr);
}

for (var l = 1; l <= 10000; l += 1) {
  addLine("This is Line " + l + ", and some extra text");
}

table.appendChild(tbody);
&#13;
<table>
  <thead><tr><th>Test</th></tr></thead>

</table>
&#13;
&#13;
&#13;