下面是使用jQuery IE8泄漏内存死简单的网页(我通过看我的iexplore.exe进程比增长在Windows任务管理器时的内存使用情况检测内存泄漏):
<html>
<head>
<title>Test Page</title>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<script type="text/javascript">
function resetContent() {
$("#content div").remove();
for(var i=0; i<10000; i++) {
$("#content").append("<div>Hello World!</div>");
}
setTimeout(resetTable, 2000);
}
$(resetContent);
</script>
<div id="content"></div>
</body>
</html>
显然,即使在调用时jQuery.remove()
函数我仍然遇到一些内存泄漏。 我可以写经历没有内存泄漏如下我自己删除功能:
$.fn.removeWithoutLeaking = function() {
this.each(function(i,e){
if( e.parentNode )
e.parentNode.removeChild(e);
});
};
这一切正常,并没有泄漏任何记忆。 那么,为什么jQuery的内存泄漏? 我创建了一个基于另一个remove函数jQuery.remove()
这确实导致泄漏:
$.fn.removeWithLeakage = function() {
this.each(function(i,e) {
$("*", e).add([e]).each(function(){
$.event.remove(this);
$.removeData(this);
});
if (e.parentNode)
e.parentNode.removeChild(e);
});
};
有趣的是,内存泄漏似乎是由每个调用哪个jQuery包含以防止内存泄漏从与被删除的DOM元素相关联的事件和数据造成的。 当我打电话removeWithoutLeaking
功能,那么我的记忆中停留一段时间不变,但是当我打电话removeWithLeakage
不是那么它只是不断增长。
我的问题是,怎么样,每个呼叫
$("*", e).add([e]).each(function(){
$.event.remove(this);
$.removeData(this);
});
可能被导致内存泄漏?
编辑:在码修正错字,其在重新测试,证明对结果没有任何影响。
进一步编辑:我已经提交给jQuery的项目的bug报告,因为这似乎是一个jQuery错误: http://dev.jquery.com/ticket/5285
我想大卫可能会在一些与涉嫌removeChild之泄漏,但我不能在IE8重现它...它可以在早期的浏览器以及发生的,但是这不是我们这里。 如果我手动removeChild之的div没有泄露; 如果我改变jQuery来使用outerHTML= ''
(或移动到仓随后bin.innerHTML)代替removeChild之仍然存在泄漏。
在淘汰的过程,我开始在位黑客remove
jQuery中。 1.3.2线1244:
//jQuery.event.remove(this);
jQuery.removeData(this);
注释掉该行没有导致泄漏。
那么,让我们来看看event.remove,它调用data('events')
以查看是否有连接到元素的任何事件。 什么是data
在做什么?
// Compute a unique ID for the element
if ( !id )
id = elem[ expando ] = ++uuid;
哦。 所以,它的加入jQuery的UUID到数据查找条目劈特性之一每个元素甚至尝试读取数据上,其中包括你移除元素的每一个后代! 多么愚蠢。 我可以短路,通过加入这行之前它:
// Don't create ID/lookup if we're only reading non-present data
if (!id && data===undefined)
return undefined;
这似乎修复泄漏对于这种情况在IE8。 不能保证它不会打破东西是jQuery的迷宫一样,但在逻辑上是有意义的。
至于我可以工作,泄漏简直是jQuery.cache
对象(也就是数据存储,而不是一个真正的高速缓存这样)越来越大,作为一个新的关键是为每个删除的元素加入。 虽然removeData应删除这些缓存条目OK,IE不会出现,当你恢复空间delete
从对象的关键。
(无论哪种方式,这是哪门子的jQuery的行为,我不欣赏的一个例子,它是橱什么应该是一个平凡简单的操作......其中一些下做太多是很值得怀疑的东西,整个用的expando和东西什么jQuery不会给innerHTML
通过正则表达式来防止显示在IE属性是刚刚打破和丑陋,而且使消气的习惯和setter相同功能的混乱,在这里,在错误的结果。 )
[古怪,留下leaktest为长时间结束了偶尔给完全虚假的错误在jquery.js和之前的记忆居然跑了出来......还有像“意想不到的命令”,我注意到一个“节点名称为空或不对象”在行667,这是据我可以看到甚至不应该已经在运行,更谈不上有对节点名称是空的检查有! IE浏览器是不是给我很大的信心在这里...]
似乎是固定jQuery中1.5(23二月版本)。 我跑进与1.4.2同样的问题,并与DOM去除如上第一固定,然后通过尝试新的版本。
元素移除一个内在的DOM问题。 这是要和我们呆在一起。 同上。
jQuery.fn.flush = function()
/// <summary>
/// $().flush() re-makes the current element stack inside $()
/// thus flushing-out the non-referenced elements
/// left inside after numerous remove's, append's etc ...
/// </summary>
{ return jQuery(this.context).find(this.selector); }
相反黑客JQ的,我用这个扩展。 特别是在大量删除()和克隆()的网页:
$exact = $("whatever").append("complex html").remove().flush().clone();
同时,也是下一个确实的帮助:
// remove all event bindings ,
// and the jQ data made for jQ event handling
jQuery.unbindall = function () { jQuery('*').unbind(); }
//
$(document).unload(function() {
jQuery.unbindall();
});
看到了jQuery 1.4路线图http://docs.jquery.com/JQuery_1.4_Roadmap 。 具体而言,节“卸下摆臂后使用.outerHTML清理()”与IE发生由于remove函数内存泄漏问题的交易被调用。
也许你的问题会在下一版本中得到解决。
它是否仍然泄漏如果调用empty
,而不是remove
?
$("#content").empty();
JQuery的1.4.1有以下几点:
cleanData: function (elems) {
for (var i = 0, elem, id; (elem = elems[i]) != null; i++) {
jQuery.event.remove(elem);
jQuery.removeData(elem);
}
}
这里是我不得不修改,以消除漏水的问题是什么:
cleanData: function (elems) {
for (var i = 0, elem, id; (elem = elems[i]) != null; i++) {
jQuery.event.remove(elem);
jQuery.removeData(elem);
jQuery.purge(elem);
}
}
附加功能:
purge: function (d) {
var a = d.childNodes;
if (a) {
var remove = false;
while (!remove) {
var l = a.length;
for (i = 0; i < l; i += 1) {
var child = a[i];
if (child.childNodes.length == 0) {
jQuery.event.remove(child);
d.removeChild(child);
remove = true;
break;
}
else {
jQuery.purge(child);
}
}
if (remove) {
remove = false;
} else {
break;
}
}
}
},