Proper Iteration Methods for HTMLCollection in JavaScript and Their Evolution

Nov 03, 2025 · Programming · 11 views · 7.8

Keywords: HTMLCollection | JavaScript Iteration | DOM Manipulation | For Loops | Browser Compatibility

Abstract: This article provides an in-depth analysis of HTMLCollection iteration in JavaScript, explaining why for/in loops cause undefined results and systematically introducing correct iteration methods including for loops, for/of loops, and Array.from(). It traces the historical evolution of browser support for DOM list iteration and offers comprehensive guidelines for developers through comparative analysis of different approaches.

Problem Background and Error Analysis

In JavaScript development, HTMLCollection is a common DOM element collection object returned by methods such as document.getElementsByClassName() and document.getElementsByTagName(). Many developers encounter unexpected results when attempting to iterate over HTMLCollection using for/in loops.

Consider the following typical erroneous code example:

var list = document.getElementsByClassName("events");
console.log(list[0].id); // Correct output: event1
for (key in list) {
    console.log(key.id); // Incorrect output: undefined
}

The first console.log correctly outputs event1, while the second outputs undefined. This occurs because the for/in loop iterates over the enumerable properties of an object. In HTMLCollection, the key variable represents property names (indices 0, 1, 2, etc.) rather than the element objects themselves.

Misuse Analysis of for/in Loops

The for/in loop is designed for iterating over object properties, not specifically for arrays or array-like objects. HTMLCollection contains not only element indices but also other built-in properties:

// In Firefox, for/in iteration over HTMLCollection returns:
// 0, 1, 2, item, namedItem, @@iterator, length

When using key.id, you're actually accessing the id property of the property name, and property names (like "0", "length") don't have an id property, hence returning undefined.

The correct usage of for/in would be:

for (key in list) {
    if (list.hasOwnProperty(key) && !isNaN(key)) {
        console.log(list[key].id);
    }
}

However, this approach is complex and error-prone, not recommended for practical development.

Recommended Iteration Methods

Traditional for Loop

The most compatible and reliable iteration method, suitable for all browser environments:

var list = document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
    console.log(list[i].id);
}

This method directly accesses elements through indices, offering excellent performance and clear code structure.

ES6 for/of Loop

Modern browsers support direct iteration over HTMLCollection using for/of:

var list = document.getElementsByClassName("events");
for (let item of list) {
    console.log(item.id);
}

Note that loop variables must be declared with let or const to avoid variable hoisting and closure issues.

Array.from() Conversion

Convert HTMLCollection to an array to utilize all array methods:

var list = document.getElementsByClassName("events");
Array.from(list).forEach(function(item) {
    console.log(item.id);
});

Or simplify with arrow functions:

Array.from(list).forEach(item => console.log(item.id));

Browser Support Evolution

ES6 Standard Support Timeline

Browser support for HTMLCollection and NodeList iteration evolved through multiple phases:

2015: ES6 introduced Array.from() method, providing a standard way to convert array-like objects to arrays.

Early 2016: Required manual addition of iterator support for DOM lists:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

December 2016: Chrome v54 and Firefox v50 built-in support for Symbol.iterator.

December 2017: Edge 41 supported for/of iteration for NodeList but not HTMLCollection.

March 2018: Safari added support for for/of iteration on both DOM list types.

November 2018: Edge 18 finally provided complete support for for/of iteration on both HTMLCollection and NodeList.

Practical Applications and Considerations

Event Listener Implementation

When adding event listeners to HTMLCollection, pay attention to variable scope issues:

// Correct implementation
const listItems = document.getElementsByTagName('li');
for (let item of listItems) {
    item.addEventListener('mouseover', () => {
        item.textContent = item.textContent.toUpperCase();
    });
}

// Or using event target
for (let item of listItems) {
    item.addEventListener('mouseover', (e) => {
        e.target.textContent = e.target.textContent.toUpperCase();
    });
}

Performance Considerations

Different iteration methods vary in performance characteristics:

Summary and Best Practices

Based on current browser support and performance considerations, the following practices are recommended:

  1. Prefer for/of loops in modern projects for concise code and good performance
  2. Use traditional for loops when backward compatibility is required
  3. Use Array.from() conversion when array methods are needed
  4. Avoid using for/in loops for HTMLCollection iteration entirely
  5. Pay attention to loop variable scope to avoid closure-related issues

By understanding HTMLCollection characteristics and selecting appropriate iteration methods, developers can avoid common pitfalls and write more robust, maintainable JavaScript code.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.