【发布时间】:2018-07-03 10:58:57
【问题描述】:
我正在循环从 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>');
}
结果 => 内存泄漏我的 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>';
}
结果 => 内存泄漏,我的 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
结果 => 没有内存泄漏
好的,直到这里我得出结论,首先,.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 : ''
}
结果 => 内存泄漏我的 RAM 去了 2Go,我的浏览器崩溃了
我的问题是:
当我们调用发生在循环之外的函数时,可能会导致内存泄漏,为什么?
如何避免这种情况(不删除函数或将其处理移至循环内部)?
【问题讨论】:
-
尝试在数组中推送
html字符串,并在将其分配给innerHTML时使用Array.join()方法 -
问题仅仅是因为你在一个循环中进行了数千个 DOM 操作,速度非常快。在不了解浏览器 JS 引擎内部结构的情况下,可以肯定地说这并不理想。这就是您创建的第三种方法(在内存中构建 HTML 字符串,然后将其附加到单个 DOM 操作中)性能最佳的原因。这是所有 DOM 附加应该完成的方式,但在大多数情况下,它们的规模很小,以至于不会注意到任何性能问题。
-
it may causes a memory leak, why ?这里没有内存泄漏.. -
@RoryMcCrossan 是的,我同意,但我现在卡在第 4 种情况下,我不能在循环中使用函数
-
您遇到的行为很正常。您正在生成 1000 个 DOM 元素。我不知道您的具体项目需求是什么,但我建议您重新考虑您的 UI,方法是放置一个按钮来限制屏幕上的对象或使用延迟加载
标签: javascript jquery ajax memory memory-leaks