带有基本 jquery ui 插件的 IE6 中的 javascript 内存泄漏

标签 javascript jquery jquery-ui memory-leaks internet-explorer-6

首先,我对这个问题进行了广泛的阅读和研究。已经有一个带有 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 之类的值,您将很容易看到内存增加。还有一个tool来自 Microsoft,您也可以使用它来检测泄漏。

所以泄漏是由于小部件的 _createWidget 方法中的自定义事件绑定(bind):

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

因此,如果我将它们注释掉,就不会泄漏。我使用的是 1.8.9 而不是 master,因为 1.8.9 的小部件代码似乎更简单(master 发生了一些变化)。

现在,如果我将同一事件完全绑定(bind)到小部件外部,也不会发生泄漏。例如,我会在创建小部件之后但在销毁之前插入以下代码:

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

我特意添加了一个无操作函数,但回调函数中的内容并不重要。您可能会争辩说,因为之后我正在手动销毁,所以绑定(bind)不是必需的。但这不是重点。

所以我的问题是为什么原始代码,即小部件代码中的绑定(bind)调用会泄漏?我怀疑这是因为关闭,但我无法解释。

谁能解释一下?

最佳答案

据我了解,当 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

关于带有基本 jquery ui 插件的 IE6 中的 javascript 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4998997/

相关文章:

java - Node.js 和 Java

jquery - 定位不同尺寸的 float 元素

javascript - React/JSX 范围

javascript - jQuery:在不使用 id 的情况下获取对特定元素的引用

javascript - 用JS改变一个div的多个属性

javascript - 根据 ID 打开 JQuery Accordion

javascript - 类似 treeview 的 jquery 插件

jQueryUI 自动完成值与标签不同

javascript - 清除 ASP.net 中的按钮名称参数

javascript - 容器外的 Jquery UI 多个可放置仍然可放置