Removing HTMLCollection elements from the DOM

The problem is that paragraphs is a live list. By removing a p element, you are also changing that list. A simple fix is to iterate over the list in reverse order:

for (var i = paragraphs.length - 1; i >= 0; --i) {
  paragraphs[i].remove();
}

The alternative solution is to create a static list (non-live list). You can do this by either:

  • converting the list into an Array:

    var paragraphs =
      Array.prototype.slice.call(document.getElementsByTagName('p'), 0);
    
  • using document.querySelectorAll:

    var paragraphs = document.querySelectorAll('p');
    

You can then iterate over the list in regular order (using a for loop):

for (var i = 0; i < paragraphs.length; ++i) {
  paragraphs[i].remove();
}

or (using a for...of loop):

for (var paragraph of paragraphs) {
  paragraph.remove();
}

Note that .remove is a relatively new DOM method, and not supported in every browser. See the MDN documentation for more info.


To illustrate the problem, let’s imagine we have a node list of three elements, paragraphs = [p0, p1, p2]. Then this is what happens when you iterate over the list:

i = 0, length = 3, paragraphs[0] == p0  => paragraphs = [p1, p2]
i = 1, length = 2, paragraphs[1] == p2  => paragraphs = [p1]
i = 2, length = 1, END

So in this example, p1 is not deleted because it is skipped.

Leave a Comment