'Add/remove listeners on JavaScript ( garbage collector )

I have a quick question regarding on adding/removing listeners of a DOM object. I would like to ask if the garbage collector be able to collect the memory when removing elements from the page.

Example: a <ul> tag with a couple list of children(<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();


Solution 1:[1]

Not at all, you can access to the ul variable somewhere else. The example below showing that.

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

The example is not a normal case. The normal case is that you want to access a DOM reference in an event say "button click". That reference will be always available as long as the event isn't unbind. For example:

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

To avoid memory leak in JS:

  1. make sure that there are no DOM references by using jQuery for example.
  2. if you use DOM references in you application, set them to null or undefined when they are not in use.

So you can modify your event a little bit as below.

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

Solution 2:[2]

If someone can confirm this for me I'd appreciate it.

From my understanding, yes it will be garbage collected. According to MDN Memory Management

The main notion garbage collection algorithms rely on is the notion of reference. Within the context of memory management, an object is said to reference another object if the former has an access to the latter (either implicitly or explicitly). For instance, a JavaScript object has a reference to its prototype (implicit reference) and to its properties values (explicit reference).

Essentially if the DOM cannot find a reference to said element, it will garbage collect it sometime in the near future. Looking at the DOM Standard specification of how .remove() works, it will run a series of steps that will set the new indexes of parents and siblings removing all references to the element.

Because there are no references to said element, it will be garbage collected. In your example, you are adding eventListeners only to the children of the specific <ul> element you created. When you remove an element, you also remove all references of its children as well (I think this is clearer in the steps in the link above where they actually set the parent index to point to itself).

EDIT: @contrabit is right though. I didn't see you stored your children in a variable. As long as their is a reference to them, they won't be garbage collected.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nhân Nguyê?n
Solution 2 aug