I have a collection of paragraph elements. Some are empty and some contain whitespace only, while others have content:
Pellentesque habitant morbi t
The HTMLCollection is mutating (changing) while you are removing nodes, the the length gets out-of-sync with the "real" length of the HTMLCollection array.
Lets say you have an array of 2 DOM nodes, and you are iterating it. it should iterate 2 times. The demo below illustrate this perfectly and i easy to follow:
first iteration - removes the first node and then i is incremented.
second iteration - now i equals to 1 but the paragraphs.length is now also 1 because only one paragraph is left at this point.
This results in an impossible scenario where an array with length of 1 is asked to access an item at position 1, and the only position available is 0 (since Arrays start from position 0...)
Accessing a position which doesn't exist in an Array (or Array-like object HTMLCollection) is illegal.
var paragraphs = document.getElementsByTagName('p')
for (var i = 0; i <= paragraphs.length; i++) {
console.log(i, paragraphs.length)
paragraphs[i].remove()
}
1
2
In the below demo the removal of nodes is made after all cycles of iteration has been made (setTimeout delays code execution), and the key here is to utilize the third parameter and pass the node which will be cached as the argument for the timeout callback:
var paragraphs = document.getElementsByTagName('p')
for (var i = 0, len = paragraphs.length; i < len; i++) {
setTimeout(node => node.remove(),0 , paragraphs[i])
}
Pellentesque habitant....
Also it's important not to increment i since the length of the array keeps shrinking, the first item gets removed on every iteration until no more items are left
var paragraphs = document.getElementsByTagName('p')
for (var i = 0, len = paragraphs.length; i < len; ) {
if( paragraphs[i] )
paragraphs[i].remove()
}
1
2
3
var paragraphs = document.getElementsByTagName('p')
for (var i = paragraphs.length; i--; ){
paragraphs[i].remove() // could also use `paragraphs[0]`. "i" index isn't necessary
}
1
2
3