【问题标题】:Am i creating a memory leak?我在创建内存泄漏吗?
【发布时间】:2012-10-01 18:40:41
【问题描述】:

我有一个 JavaScript 闭包,我会在我的 Web 应用程序的整个生命周期中不断重新创建它(单个完整的 ajax 页面)。

我想知道它是否会造成内存泄漏。

这是一个例子JSFIDDLE

有问题的代码:

function CreateLinks() {

    var ul = $("<ul></ul>").appendTo('div#links');

    for (var i in myLinks) {

        var li = $('<li>' + myLinks[i].name + '</li>').appendTo(ul);

        //closure starts here
        (function (value) {
            li.click(function (e) {
                $('div#info').append('<label>' + value + '</label><br />');
                RecreateLinks();
            });
        })(myLinks[i].value);

    }
}

【问题讨论】:

  • 在那里关闭有什么意义?为什么不说var value = myLinks[i].value;直接运行代码呢?
  • @Jacob:哦,我明白了。你的意思是myLinks[i].value,对。
  • 以上代码没有内存泄露。但是解决问题的方法太复杂了
  • 闭包有一个目的,测试并将this jsfiddle与我的问题中的那个进行比较......这个只为所有链接输出“tres”。
  • 你不能把电话放在setInterval(method, 10); 中,然后观察你的操作系统统计数据,看看你的浏览器应用程序的内存是否增加了?我知道除了闭包还有更多的事情发生,但是 jQuery 的内存效率很高

标签: javascript memory-leaks


【解决方案1】:

如果您确保避免在RecreateLinks() 函数中绑定多个click 处理程序,您应该没问题;这可以通过显式取消绑定现有节点、删除 DOM 节点或确保您不会添加多个 click 处理程序来完成。

浏览器在内存分配策略方面做得越来越好,但您不应该假设太多。如果内存使用是一个大问题,请尽量避免创建太多您不确定它们是否会被垃圾收集的闭包。一种这样的方法是使用.data() 来存储您的值对象,然后使用通用的点击处理程序而不是闭包。

分析 JavaScript 并不是那么简单; Chrome 确实有一个 Profile 工具,可以监控 CPU 和数据性能。这可以让您很好地衡量预期的内存消耗,但 Chrome 并不是所有的浏览器,请记住这一点。

【讨论】:

  • 闭包不是只被li 元素引用,而这些元素在RecreateLinks() 中被删除了吗?
  • 我无法从RecreateLinks() 访问li 点击处理程序。也许你可以更新 jsfiddle 并告诉我你的意思。
  • @capdragon 删除元素本身也可以。除非你确定你永远不会多次绑定点击事件,这提醒我你也可以使用 .one()
  • @capdragon 添加了另一个您可以采纳的建议。
  • @Jack 感谢您的建议(+1)。但是,不乏解决方法或解决方案。我只是想知道闭包是否会造成内存泄漏。我想要一些证据来证明这一点和/或我自己可以看到的方法。
【解决方案2】:

根据浏览器的智能程度,最好在&lt;li&gt; 上添加“myLinks[i].value”属性,而不是通过闭包传递。当事件处理程序从其范围之外引用变量时,某些愚蠢的浏览器会出现收集垃圾的问题。 JavaScript 和 DOM 运行两种不同的 GC,而 JS 一个没有意识到 DOM 元素/事件处理程序已经消失并且变量不再使用。这个问题可以通过通过 javascript 正确删除事件处理程序来解决,而不是仅仅处理它所附加的元素。

类似于:

li.attr('lvalue',myLinks[i].value);
...
var value = $(this).attr('lvalue');

此设置还允许您使用

$('#links > ul > li').live('click',function(){...});

这将消除每次添加单个事件的需要。

【讨论】:

  • (+1) 感谢您的建议,这将起作用...事情是 myLinks[i].value 在我的应用程序中是一个相当大的对象。也就是说,它是一个具有许多属性和方法的对象。我在这里做的很简单,只是作为一个例子。我想将每个属性/方法映射到一个 li 属性是不好的。
  • @capdragon 您可以在代码中使用 js 对象,并在 li 标签上使用该对象的 id。
  • 你是对的,我想这是另一种方式。不过,我真的只想知道闭包是否会造成内存泄漏。我想要一些证据来证明这一点和/或我自己可以看到的方法。
  • 我希望存在这样的工具,根据我的经验,跟踪网页的内存或 CPU 使用情况几乎是不可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多