4

首先,我对这个问题进行了广泛的阅读和研究。我已经有一张jquery UI的门票了。我知道解决这个问题的方法,但我很好奇为什么会发生这种情况。我相信这个错误是由于关闭,但我的javascript-fu不是专家。IE6中的javascript内存泄漏与基本的jQuery UI插件

我图的jQuery UI的团队有更重要的事情做多花精力上的IE6的bug。所以我想把这个提供给一般的javascript public。

下面是一个测试用例:

<!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主的所有组合进行测试(如书写的)但它们都产生相同的结果。

我的测试widget是我相信你可以得到最简单的。

如果测试使用sIEve,你可以当场泄漏。否则,将计数器增加到1000之类的值,你会看到内存很容易增加。还有另一个来自Microsoft的tool,您可以使用它来检测泄漏。

所以泄漏是由于自定义事件在widget的_createWidget方法结合:

var self = this; 
this.element.bind("remove." + this.widgetName, function() { 
    self.destroy(); 
}); 

所以,如果我评论者淘汰,没有泄漏。我使用的是1.8.9而不是主控,因为1.8.9的Widget代码看起来更简单(主控已经改变了一下)。

现在,如果我绑定控件外部的同一事件完全,也没有泄漏。例如,我会插入下面的代码后,我创建的组件,但是之前破坏:

$("#inner").bind("remove.test", function() {}); 

我有意添加无操作功能,但它并不重要什么是回调函数内。你可能会争辩,因为我之后手动进行销毁,所以绑定不是必需的。但那不是重点。

所以我的问题是,为什么原来的代码,结合呼叫从控件代码内漏?我怀疑是因为封闭,但我无法解释。

有人可以解释这一点吗?

回答

2

据我所知时,有回指向JS和DOM中,当一个JS变量指向一个DOM对象,并且该DOM对象具有属性(或,通常是,事件处理程序)之间的循环引用它发生问题到JS变量。你的例子与.bind()似乎这样做。显然,IE在其垃圾收集过程中使用引用计数,并且没有收集循环引用。

我已经看到至少有几个MSDN博客指责这在JavaScript上,基本上建议避免闭包,这显然不是很有帮助,但这里有一些非Microsoft/MSDN文章讨论这个问题并给出一些解决方法:

http://laurens.vd.oever.nl/weblog/items2005/closures/

http://www.ibm.com/developerworks/web/library/wa-memleak/

JavaScript Closures and Memory Leaks

+0

+1老鼠!闭包是JavaScript的最好的部分! – ClosureCowboy 2011-02-15 02:54:35

0

我很抱歉,我不能提供一个解释到CA使用这个问题,但我的工作解决方案,以防止这种相当恼人的泄漏发生。

包括在我的网页jQuery和jQuery的用户界面后,我加入以下代码:

var origCreateWidget = $.Widget.prototype._createWidget; 
$.Widget.prototype._createWidget = function(options, element) { 
    var origBind = $.fn.bind; 
    var widget = this; 
    $.fn.bind = function(type, func) { 
     if(typeof(type) === "string" && type.indexOf("remove.") === 0) { 
     // ignore the remove events 
     } 
     else { 
     origBind.apply(this, arguments); 
     } 
     return this; 
    } 

    var res = origCreateWidget.call(this, options, element); 

    $.fn.bind = origBind; 
    return res; 
}; 

此外,我打电话destroy当窗口卸载事件发生。在这些更改之后,sIEve不会报告任何泄漏,并且在浏览包含可排序小部件的页面时,Windows任务管理器显示持续的内存消耗。

经过数小时的搜索和测试,我仍然无法弄清楚泄漏的真正原因。