HTMLCollectionAn HTMLCollection is an array-like, live list of HTML elements returned by DOM properties such as element.children, document.forms, and getElementsByClassName(). Because it stays wired to the live document, adding or removing matching elements updates the collection immediately.
HTMLCollection vs. Static NodeListEven though both look like arrays with .length and [0] index access, an HTMLCollection differs in three important ways:
collection.length right away during your loop..forEach() and .map(): Calling el.children.forEach(...) throws a TypeError because HTMLCollection does not implement .forEach()..namedItem(): You can access elements with id or name attributes via collection["myId"] as well as numeric indexes.HTMLCollection to a Real ArrayConvert an HTMLCollection with spread syntax [...collection] or Array.from(collection) so you get full array methods (.map(), .filter(), .find()) and a safe static snapshot.
const app = document.getElementById("app");
if (app) {
app.innerHTML = `<div class="chip">JS</div><div class="chip">DOM</div>`;
const liveChips = app.getElementsByClassName("chip");
console.log("Initial live count:", liveChips.length);
// Convert to static array before mutating or mapping
const labels = [...liveChips].map((node) => node.textContent);
console.log("Chip labels:", labels);
const extra = document.createElement("div");
extra.className = "chip";
extra.textContent = "Async";
app.append(extra);
// Notice liveChips.length updated automatically without re-querying!
console.log("Updated live count:", liveChips.length);
}
HTMLCollection: Writing for (let i = 0; i < divs.length; i++) { container.append(newDiv); } makes divs.length grow on every pass, freezing the tab forever!for loop: Removing items[0] shifts items[1] into index 0, so i++ skips it. Loop over a static copy [...items] instead..forEach() directly on element.children: Always wrap [...element.children].forEach(...) or use a for...of loop.HTMLCollection with for...of?Yes, modern browsers implement [Symbol.iterator] on HTMLCollection, so for (const child of parent.children) works cleanly without conversion.
querySelectorAll() usually preferred over getElementsByClassName()?querySelectorAll() returns a static NodeList that has .forEach() built in, accepts full CSS selectors, and never shifts under your feet when elements are added or removed.
HTMLCollection.length repeatedly hurt speed?Yes, accessing .length inside tight loops can force the browser to re-verify DOM matches; cache const items = [...collection] once before looping.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.