簡體   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