Skip to content Skip to sidebar Skip to footer

Why ForEach Array Method Is Not A Function On Looping Over Document.getElementsByClassName

In order to get the matched elements & loop over it , I am using querySelectorAll & forEach array method. According to this,querySelectorAll will return a nodelist. I can

Solution 1:

document.querySelectorAll returns a NodeList not an Array. Never fear, tho!

You can use Function.prototype.call to change the context of the Array.prototype.forEach function.

var nodes = document.querySelectorAll('span');
var colors = ['red', 'orange', 'gold', 'lawngreen', 'dodgerblue', 'deepskyblue', 'blueviolet'];

Array.prototype.forEach.call(nodes, function(elem, idx) {
  // do something
  elem.style.color = colors[idx];
});
<span>A</span>
<span>B</span>
<span>C</span>
<span>D</span>
<span>E</span>
<span>F</span>
<span>G</span>

EDIT

Actually my doubt is why forEach does not directly work on return of document.getElementsByClassName

That's because document.getElementsByClassName reutrns an HTMLCollection not an Array. HTMLCollection does not have a forEach method on its prototype.

var nodes = document.getElementsByTagName('span');
console.log(nodes.constructor.name);
//=> HTMLCollection 
<span>A</span>

Solution 2:

From what I tested:

<ul>
    <li class="test"></li>
    <li class="test"></li>
    <li class="test"></li>
    <li class="test"></li>
    <li class="test"></li>
    <li class="test"></li>
    <li class="test"></li>
</ul>
<script type="text/javascript">
    var elementList = document.querySelectorAll("li");
    console.log(elementList.constructor);
    var elementList2 = document.getElementsByClassName("test");
    console.log(elementList2);
    console.log(elementList2.constructor);
</script>

querySelectorAll returns:

NodeList() { [native code] }

while getElementsByClassName returns:

HTMLCollection() { [native code] }

Pretty much, as the previous answer mentioned, the HTML collection doesn't have access to the forEach method.

EDIT1: Difference between HTMLCollection, NodeLists, and arrays of objects seems to answer some of the differences!

EDIT2: It seems like you can iterate through an HTML Collection with the technique using ES6 mentioned here: For loop for HTMLCollection elements


Solution 3:

We can interact with an HTML Collection as if it’s an array in many other ways. We can use index numbers to access data. It looks like an array. But it functions a bit differently. First of all, a bit of a distinction. I’ve heard nodeList and HTMLCollection used somewhat interchangeably. They’re both DOM lists, but the only real difference is that HTMLCollection is more specific. It contains DOM elements that are the same, whereas a nodeList can contain a variety of DOM elements. That’s why querySelectorAll returns a nodeList but getElementsByTagName returns an HTMLCollection. Interestingly enough, forEach works on a nodeList but not an HTMLCollection.

Now there are a number of ways to iterate over a HTMLCollection;

  1. var p = document.getElementsByTagName("p") for(var i = 0; i < p.length; i++) { console.log(p)} Check other ways here https://medium.com/@larry.sassainsworth/iterating-over-an-html-collection-in-javascript-5071f58fad6b

Post a Comment for "Why ForEach Array Method Is Not A Function On Looping Over Document.getElementsByClassName"