繁体   English   中英

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

[英]add/remove listeners on javascript ( garbage collector )

关于添加/删除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();

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

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

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

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

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

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

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

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或undefined。

所以您可以稍微修改一下您的活动。

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

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

根据我的理解, 是的 ,它将被垃圾收集。 根据MDN内存管理

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM