首先,我在这个问题上进行了广泛的阅读和研究.已经有一张
jquery UI的票,我正在关注它.我知道解决这个问题的方法,但我很好奇为什么会这样.我相信错误是由于关闭,但我的javascript-fu不是专家.
我认为jquery UI团队有更好的事情要做,而不是花费精力在IE6上.所以我想把它带到一般的javascript公开.
以下是测试用例:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>jquery ui memory leak test</title>
<script type="text/javascript" src="jquery-1.5.js"></script>
<script type="text/javascript" src="jquery.ui.widget.js"></script>
<script type="text/javascript">
(function($) {
$.widget("ui.test", {
_create: function() {
}
});
$(document).ready(function() {
for (var i = 0; i < 1; i++) {
$("#container").append("<div id='inner'></div>");
$("#inner").test();
$("#inner").test("destroy");
$("#container").empty();
};
});
})(jQuery);
</script>
</head>
<body>
<div id="container">
</div>
</body>
</html>
我已经使用jquery 1.4.4和1.5以及jquery-ui-1.8.9和jquery-ui master(写作时)的所有组合进行了测试,但它们都产生了相同的结果.
我的测试小部件是我认为最简单的.
如果使用sIEve进行测试,则可以发现泄漏.否则,将计数器增加到1000,你会很容易看到内存增加.您还可以使用Microsoft的另一个tool来检测泄漏.
因此泄漏是由于小部件的_createWidget方法中的自定义事件绑定:
var self = this;
this.element.bind( "remove." + this.widgetName, function() {
self.destroy();
});
所以,如果我评论那些,那就没有泄漏.我使用的是1.8.9而不是master,因为1.8.9的widget代码看起来更简单(master已经改变了一点).
现在,如果我完全绑定窗口小部件之外的相同事件,也没有泄漏.例如,我在创建窗口小部件之后但在destroy之前插入以下代码:
$("#inner").bind("remove.test", function() {});
我故意添加了一个无操作函数,但回调函数里面的内容并不重要.你可以争辩说,因为我之后手动破坏,所以不需要绑定.但这不是重点.
所以我的问题是为什么原始代码,小部件代码中的绑定调用会泄漏?我怀疑这是因为关闭,但我无法解释.
有人可以解释一下吗?
最佳答案 据我所知,当JS变量指向DOM对象时,JS和DOM之间存在循环引用时会发生问题,并且该DOM对象具有指向JS变量的属性(或通常是事件处理程序) .上面的.bind()示例似乎是这样做的.显然,IE在其垃圾收集过程中使用引用计数,并且不会收集循环引用.
我已经看到至少有几个MSDN博客将此归咎于JavaScript并且基本上建议避免关闭,这显然不是很有帮助,但是这里有一些非Microsoft / MSDN文章讨论了这个问题并提供了一些解决方法:
http://laurens.vd.oever.nl/weblog/items2005/closures/