Difference between NodeList or HTMLCollection

Introduction about NodeList:
NodeList objects are collections of nodes, usually returned by properties such as Node.childNodes and methods such as document.querySelectorAll().
This interface was an attempt to create an unmodifiable list and only continues to be supported to not break code that's already using it. Modern APIs represent list structures using types based on JavaScript arrays, thus making many array methods available, and at the same time imposing additional semantics on their usage (such as making their items read-only).
These historical reasons do not mean that you as a developer should avoid NodeList. You don't create NodeList objects yourself, but you get them from APIs such as Document.querySelectorAll(), and these APIs are not deprecated. However, be careful of the semantic differences from a real array.
Although NodeList is not an Array, it is possible to iterate over it with forEach(). It can also be converted to a real Array using Array.from().
In simple words :
A NodeList is a collection of DOM nodes returned by several DOM methods.
It represents an ordered list of nodes from the DOM tree.
In the DOM, nodes can be many things:
HTML elements
Text inside elements
Comments
Document fragments
So a NodeList is more general and flexible.Example:
const items = document.querySelectorAll("li");
console.log(items);
Features
Can contain any node type (elements, text nodes, comments).
Usually static (does not update automatically when DOM changes).
Supports forEach().
Example:
items.forEach(item => {
console.log(item);
});
Characteristics:
It can contain multiple node types likes :
Elements
Text nodes
Comment nodes
It is static by default
- If the DOM changes later, the NodeList usually does not update automatically.
Iterable
Supports modern iteration methods like:
forEach()for...of
Example:
nodes.forEach(node => console.log(node));
- It is designed for modern DOM querying :
querySelectorAll() intentionally returns a NodeList because developers often want a stable snapshot of the DOM.
Live vs. Static NodeLists:
Although they are both considered NodeList objects, there are 2 varieties of NodeList: live and static.
In most cases, the NodeList is live, which means that changes in the DOM automatically update the collection.
For example, Node.childNodes is live:
const parent = document.getElementById("parent");
let childNodes = parent.childNodes;
console.log(childNodes.length); parent.appendChild(document.createElement("div"));
console.log(childNodes.length);
In other cases, the NodeList is static, where any changes in the DOM do not affect the content of the collection. The ubiquitous document.querySelectorAll() method is the only API that returns a static NodeList.
It's good to keep this distinction in mind when you choose how to iterate over the items in the NodeList, and whether you should cache the list's length.
Instance properties:
NodeList.length Read only
The number of nodes in the NodeList.
Instance methods:
NodeList.item()
Returns an item in the list by its index, or null if the index is out-of-bounds.
An alternative to accessing nodeList[i] (which instead returns undefined when i is out-of-bounds). This is mostly useful for non-JavaScript DOM implementations.
NodeList.entries()
Returns an iterator, allowing code to go through all key/value pairs contained in the collection. (In this case, the keys are integers starting from 0 and the values are nodes.)
NodeList.forEach()
Executes a provided function once per NodeList element, passing the element as an argument to the function.
NodeList.keys()
Returns an iterator, allowing code to go through all the keys of the key/value pairs contained in the collection. (In this case, the keys are integers starting from 0.)
NodeList.values()
Returns an iterator allowing code to go through all values (nodes) of the key/value pairs contained in the collection.
Example:
It's possible to loop over the items in a NodeList using a for loop:
for (let i = 0; i < myNodeList.length; i++) {
let item = myNodeList[i];
}
Don't use for...in to enumerate the items in NodeLists, since they will also enumerate its length and item properties and cause errors if your script assumes it only has to deal with element objects. Also, for...in is not guaranteed to visit the properties in any particular order.
for...of loops over NodeList objects correctly:
const list = document.querySelectorAll("input[type=checkbox]");
for (const checkbox of list) {
checkbox.checked = true;
}
Browsers also support the iterator method (forEach()) as well as entries(), values(), and keys().
Introduction to HTMLCollection:
The HTMLCollection interface represents a generic collection (array-like object similar to arguments) of elements (in document order) and offers methods and properties for selecting from the list.
An HTMLCollection in the HTML DOM is live; it is automatically updated when the underlying document is changed. For this reason it is a good idea to make a copy (e.g., using Array.from) to iterate over if adding, moving, or removing nodes.
This interface is called HTMLCollection for historical reasons, because before the modern DOM, collections implementing this interface could only have HTML elements as their items.
This interface was an attempt to create an unmodifiable list and only continues to be supported to not break code that's already using it. Modern APIs represent list structures using types based on JavaScript arrays, thus making many array methods available, and at the same time imposing additional semantics on their usage (such as making their items read-only).
These historical reasons do not mean that you as a developer should avoid HTMLCollection. You don't create HTMLCollection objects yourself, but you get them from APIs such as Document.getElementsByClassName(), and these APIs are not deprecated. However, be careful of the semantic differences from a real array.
Instance properties:
HTMLCollection.length Read only
Returns the number of items in the collection.
length returns the total number of elements in the collection.
const items = document.getElementsByClassName("box");
console.log(items.length);
If there are 5 elements with class "box", the output will be:
5
=== Code Execution Successful ===
So length = number of elements stored in the HTMLCollection.
Instance methods:
HTMLCollection.item()
Returns the specific element at the given zero-based index into the list. Returns null if the index is out of range.
An alternative to accessing collection[i] (which instead returns undefined when i is out-of-bounds). This is mostly useful for non-JavaScript DOM implementations.
HTMLCollection.namedItem()
Returns the specific node whose ID or, as a fallback, name matches the string specified by name. Matching by name is only done as a last resort, only in HTML, and only if the referenced element supports the name attribute. Returns null if no node exists by the given name.
An alternative to accessing collection[name] (which instead returns undefined when name does not exist). This is mostly useful for non-JavaScript DOM implementations.
Usage in JavaScript:
HTMLCollection also exposes its members as properties by name and index. HTML IDs may contain : and . as valid characters, which would necessitate using bracket notation for property access. Currently, an HTMLCollection object does not recognize purely numeric IDs, which would cause conflict with the array-style access, though HTML does permit these.
For example, assuming there is one <form> element in the document and its id is myForm:
let element1, element2;
// document.forms is an HTMLCollection
element1 = document.forms[0];
element2 = document.forms.item(0);
alert(element1 === element2); // shows: "true"
element1 = document.forms.myForm;
element2 = document.forms.namedItem("myForm");
alert(element1 === element2); // shows: "true"
element1 = document.forms["named.item.with.periods"];
In simple words:
An HTMLCollection is a specialized collection that contains only HTML elements.
It is returned by older DOM selection methods that existed before modern query selectors.
Example sources:
document.getElementsByClassName()
document.getElementsByTagName()
element.children
Example:
const items = document.getElementsByClassName("box");
Characteristics
- Contains only element nodes
Unlike NodeList, it never contains text or comment nodes.
Example elements included:
<div><p><button>
- Live Collection
This is the most important property.
If the DOM changes, the HTMLCollection updates automatically.
Example:
const items = document.getElementsByClassName("box");
document.body.innerHTML += "<div class='box'></div>";
console.log(items.length); // length automatically increases
- Array-like but not an array
It has:
lengthindex access
But it does not include array methods like:
map()filter()forEach()
So you usually use a loop:
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
- Legacy DOM structure:
HTMLCollection exists mainly for backward compatibility with older DOM APIs.
DOM Concept Behind Them:
Both NodeList and HTMLCollection exist because of the structure of the Document Object Model (DOM).
The DOM represents an HTML page as a tree of nodes.
Example:
Document
└── html
└── body
├── h1
├── p
└── div
Different APIs return different collections depending on what type of nodes they should include.
If the API needs all node types : NodeList
If it needs only HTML elements : HTMLCollection
Static vs Live Collections:
This is the core theoretical difference.
Static Collection (NodeList): A snapshot of the DOM at the time of query.
Example:
const items = document.querySelectorAll("li");
Even if you add a new <li>, the NodeList does not update.
Reason: Static lists improve performance and predictability.
Here's an difference between NodeList and HTMLCollection:
| Feature | NodeList | HTMLCollection |
|---|---|---|
| Contains | Any node | Only HTML elements |
| Live or Static | Usually static | Live |
forEach() |
Supported | Not supported |
| Common methods | querySelectorAll() |
getElementsByClassName() |
Conclusion :
In the Document Object Model (DOM), both NodeList and HTMLCollection are array-like collections used to store groups of DOM nodes, but they are designed with different purposes.
A NodeList is a more general collection that can contain any type of DOM node, including element nodes, text nodes, and comment nodes. It is usually static, meaning it represents a snapshot of the DOM at the moment the query was made. Modern DOM methods like querySelectorAll() return NodeList because it provides better performance and predictable behavior.
An HTMLCollection, on the other hand, is a specialized collection that contains only HTML element nodes. It is always a live collection, meaning it automatically updates whenever the DOM structure changes. Methods such as getElementsByClassName() and getElementsByTagName() return HTMLCollection.
In simple terms:
NodeList : flexible and usually static collection of nodes
HTMLCollection : element-only collection that updates automatically
Understanding the difference helps developers choose the right DOM method and avoid unexpected behavior when manipulating elements in JavaScript.




