我有一个关于添加/删除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();
答案 0 :(得分:3)
行ul.remove();
将从DOM中删除ul
元素及其所有子元素。但只要您引用了这些侦听器li
元素和ul
元素,就不会释放事件侦听器的内存。你在变量children
,someFunction
和ul
中拥有哪些。
如果你想让垃圾收集器清理所有这些,你可以这样做:
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中的内存泄漏:
所以你可以稍微修改一下你的活动。
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
存储在一个变量中。只要他们是对他们的引用,他们就不会被垃圾收集。