Search code examples
javascriptfor-loophtmlcollectionfor-of-loop

Using entries() in a for-of loop, iterating over an HTMLCollection


I'm aware that in a for-of loop, there is the ability to utilise the Array.entries() method. This works great normally, as outlined - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries.

However, if I try to do something like:

for (const [i, foo] of document.getElementsByClassName('foo').entries())
{
  console.log(`i = ${i}, foo = ${foo}`);
}

I get told that:

Uncaught TypeError: document.getElementsByClassName.entries is not a function or its return value is not iterable

I know I can just use a good old regular for loop... But:

  • Why doesn't it work?
  • Am I misunderstanding something?
  • Can I get it to work the way I want it to (other than using a regular for loop)?

My best guess is that an HTMLCollection isn't a standard array, and so doesn't have a numeric index as such...


Solution

  • Entries method is available for arrays. However, getElementsByClassName does not return an array. Instead it returns an HTMLCollection. You need to first convert it into array. There are two ways you can do that:

    1. Using Array.prototype.slice
    function toArray(arr) {
      return Array.prototype.slice.call(arr);
    }
    
    toArray(document.getElementsByClassName('foo'));
    
    1. Using ES6 spread
    function toArray(arr) {
      return [...arr];
    }
    
    toArray(document.getElementsByClassName('foo'));