Christodoulou Andreas Christodoulou Andreas - 2 months ago 12
Javascript Question

getElementsByClassName vs querySelctorAll second iteration doesnt work

I am wondering why it skips the second iteration when I am using

document.getElementsByClassName
?



var sameClass = document.querySelectorAll("p.kokos");

for ( var i = 0; i < sameClass.length; i++){
sameClass[i].className = "cool";
}

var newClass = document.getElementsByClassName("new");

for ( var i = 0 ; i<= newClass.length; i++){
newClass[i].className = "red";
}

.lw { font-size: 60px; }


.cool {
color: #00FFFF;
}
.red {
color: red;
}

<p class="kokos" id = "test">Hello Weaver!</p>
<p class="kokos" id = "test">Hello Weaver!</p>
<p class="kokos" id = "test">Hello Weaver!</p>
<p class="new" id = "test">Hello Weaver!</p>
<p class="new" id = "test">Hello Weaver!</p>
<p class="new" id = "test">Hello Weaver!</p>




Answer

document.getElementsByClassName() returns a live HTMLCollection. That means that as you modify the objects in the collection so that they no longer match the class name, the actual HTMLCollection object gets modified right out from under you, affecting your iteration.

One popular work-around is to iterate the collection in reverse order from back to front. That way, if the current element is removed from the collection, the rest of your iteration is not affected.

var newClass = document.getElementsByClassName("new");

for (var i = newClass.length - 1; i >= 0; i--){
    newClass[i].className = "red";
}

Another work-around is to make a copy of the HTMLCollection into a normal array and iterate that array instead.

document.querySelectorAll() returns a fixed collection, not a live collection so it does not have this issue.