最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

memory management - Addremove listeners on JavaScript ( garbage collector ) - Stack Overflow

programmeradmin0浏览0评论

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();

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();
Share Improve this question edited Jan 26, 2022 at 15:58 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Feb 2, 2015 at 7:53 olanchuyolanchuy 5151 gold badge4 silver badges14 bronze badges 2
  • Your loop won't work correctly. children.length is not good condition. – Luka Commented Feb 2, 2015 at 8:05
  • just a typo, will edit it thanks :) – olanchuy Commented Feb 2, 2015 at 8:17
Add a ment  | 

3 Answers 3

Reset to default 4

The line ul.remove(); will remove ul element and all of its children from the DOM. But memory for event listeners will not be released as long as you have references to those listeners, li elements, and ul element. Which you do have in variables children, someFunction and ul.

If you want to let the garbage collector clean all of these, you can do for example:

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

That way variable children will not hold the reference to those elements, and if you don't have any other variable in your code that hold the reference for those elements, garbage collector will collect them. The same holds for someFunction. Note that ul element holds all the references to its children and listeners, so ul has to be cleaned as well.

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>'
});

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.

发布评论

评论列表(0)

  1. 暂无评论