在javascript上添加/删除监听器(垃圾收集器)

时间:2015-02-02 07:53:08

标签: javascript memory-management javascript-events

我有一个关于添加/删除DOM对象的侦听器的快速问题。 我想问一下,当从页面中删除元素时,垃圾收集器是否能够收集内存。

离。一个<ul>标记,其中包含几个子项列表(<li>

var ul = document.getElementById('someParent');
var children = ul.children;
var someFunction = function() {};

for(var i = 0; i < children.length; i++) {
  children[i].addEventListener('click', someFunction);
}


// This is where I am not sure, would the garbage collector be able to collect
// the memory allocated on adding listener on children,
// if I remove the ul tag?
ul.remove();

3 个答案:

答案 0 :(得分:3)

ul.remove();将从DOM中删除ul元素及其所有子元素。但只要您引用了这些侦听器li元素和ul元素,就不会释放事件侦听器的内存。你在变量childrensomeFunctionul中拥有哪些。

如果你想让垃圾收集器清理所有这些,你可以这样做:

ul.remove();
children = null;
someFunction = null;
ul = null;

这样变量children将不会保存对这些元素的引用,如果您的代码中没有任何其他变量来保存这些元素的引用,则垃圾收集器将收集它们。同样适用于someFunction。请注意,ul元素包含对其子项和侦听器的所有引用,因此也必须清除ul

答案 1 :(得分:2)

完全没有,您可以在其他地方访问ul变量。下面的例子显示了。

var ul = document.getElementById('someParent');
ul.remove();
console.log(ul); // ul and all li tags
document.body.appendChild(ul); // ul appears again

该示例不是正常情况。通常情况下,您希望在事件中访问DOM引用,并按下&#34;按钮单击&#34;。只要事件没有解除绑定,该引用将始终可用。例如:

var ul = document.getElementById('someParent');
var myButton = document.getElementById('myButton');
myButton.addEventListener('click', function () {
    ul.innerHTML += '<li>Some text</li>'
});
ul.remove();
myButton.click(); // no exception when execting button click event

为了避免JS中的内存泄漏:

  1. 使用jQuery确保没有DOM引用 示例
  2. 如果您在应用程序中使用DOM引用,请将它们设置为null或 未使用时未定义。
  3. 所以你可以稍微修改一下你的活动。

    myButton.addEventListener('click', function () {
        // check ul belongs to visible DOM
        if (!document.body.contains(ul)) {
            ul = null;
            return;
        }
        ul.innerHTML += '<li>Some text</li>'
    });
    

答案 2 :(得分:1)

如果有人可以为我确认这一点,我会很感激。

根据我的理解,它将被垃圾收集。根据{{​​3}}

  

垃圾收集算法所依赖的主要概念是参考概念。在内存管理的上下文中,如果前者可以访问后者(隐式或显式),则称该对象引用另一个对象。例如,JavaScript对象具有对其原型(隐式引用)及其属性值(显式引用)的引用。

基本上,如果DOM找不到对所述元素的引用,它将在不久的将来垃圾收集它。查看关于MDN Memory Management如何工作的DOM标准规范,它将运行一系列步骤,设置父项和兄弟项的新索引,删除对该元素的所有引用。

因为没有对所述元素的引用,所以它将被垃圾收集。在您的示例中,您只将eventListeners添加到您创建的特定<ul>元素的子元素中。当你删除一个元素时,你也删除了它的子元素的所有引用(我认为这在上面链接的步骤中更清楚,它们实际上将父索引设置为指向它自己)。

编辑:@ contrabit是正确的。我没有看到你将children存储在一个变量中。只要他们是对他们的引用,他们就不会被垃圾收集。