HTMLCollection and NodeList in JavaScript Document Object Model (DOM): A Comprehensive Guide

Wasiu Akindoyin
Coinmonks
13 min readMay 10, 2024

--

· Introduction
· What is HTMLCollection?
· What is a NodeList?
· Similarities between HTMLCollection and NodeList
Array-like Behaviour
Length Property
· Differences between HTMLCollection and NodeList
1. Content
2. Live Collections vs. Static Collections
3. Accessing Elements
4. Obtaining
· Choosing the Right Tool
HTMLCollection
NodeList
· Conclusion

Introduction

Have you ever navigated the complex world of JavaScript’s Document Object Model (DOM) and come across the terms HTMLCollection and NodeList? These objects are similar, but they serve different purposes when working with web page elements. These objects show different characteristics and behaviours that every web developer should know.

In this article, you will embark on a journey to learn, and understand HTMLCollection and NodeList. Starting from their origins to their significance in modern web development, you will learn their similarities, differences, and real-world applications of these objects. Following this article to the end, you will be able to confidently navigate the fascinating world of DOM manipulation.

What is HTMLCollection?

HTMLCollection is an interface in the DOM that represents a collection of HTML document elements. It is commonly used when you want to access a group of elements with a specific tag name or class name, such as all <div> elements or all <p>elements, or when you want to access elements within a specific container, such as all elements within a <ul> element.

HTMLCollectionis live, meaning that it is automatically updated when the underlying document is modified. This means that if elements are added, removed, or modified in the document, the HTMLCollection object will reflect those changes immediately. HTMLCollection can be accessed via methods such as getElementByTagName(), and getElementByClassName().

An example of the JavaScript DOM method using the getElementByTagName().

Code example:

<p class="para">First Paragraph</p>
<p class="para">Second Paragraph</p>
<p class="para">Third Paragraph</p>

In the code example above, we have three HTML <p> tags each with the class name para. Now, let's select them using the JavaScript getElementByClassName() method.

let paraEl = document.getElementsByTagName('p');
console.log(paraEl);

The JavaScript code above retrieves all the HTML <p> elements in the document using getElementsByTagName() and stores them in a variable namedparaEl. The getElementsByClassName() method returns an HTMLCollection and then the result is printed to the console using console.log. A screenshot of the result is below.

What is a NodeList?

A NodeList is another interface in the DOM that represents a collection of document nodes (element nodes, attribute nodes, text nodes, comments, essentially any type of node in the DOM tree), typically used in the context of web development with JavaScript.

A NodeList is most often a static collection. NodeList objects are commonly returned by methods like querySelectorAll() and properties like childNodes() and children when accessing elements in the DOM. They can be iterated over using methods like forEach() or by accessing them by index, like an array.

An example of the JavaScript DOM method using the querySelectorAll().

Code example:

<p class="para">First Paragraph</p>
<p class="para">Second Paragraph</p>
<p class="para">Third Paragraph</p>

In the code example above, we have three HTML <p> tags each with the class name para. Now, let's select them using the JavaScript querySelectorAll() method instead.

let paraEl = document.querySelectorAll('p');
console.log(paraEl);

The JavaScript code above retrieves all the HTML <p> elements in the document using querySelectorAll() and stores them in a variable named paraEl. The querySelectorAll() method returns a NodeList and then the result is printed to the console using console.log. A screenshot of the result is below.

Similarities between HTMLCollection and NodeList

HTMLCollection and NodeList have several key similarities, including:

Array-like Behaviour

HTMLCollection and NodeList both resemble arrays. Even though they are not true arrays, they resemble arrays in their structure. You can access elements within them using zero-based indexing (starting from index 0). This means you can use the index to retrieve a specific element, like sample[0] for the first element in the array.

Length Property

HTMLCollection and NodeList both have the length property, which indicates the total number of elements contained in the collection. This allows you to iterate through the collection using loops or other array-like methods.

Example:

<p class="para">First Paragraph</p>
<p class="para">Second Paragraph</p>
<p class="para">Third Paragraph</p>

This is a <p> tag with three paragraphs. Let’s see examples of accessing the elements with zero-based indexing and also checking the length for both HTMLCollection and NodeList.

In the code example above, we have three HTML <p> tags each with the class name para. Let’s see examples of accessing the elements with zero-based indexing and also checking the length for both HTMLCollection and NodeList.

Example of array-like behaviour and length property with HTMLCollection:

// The getElementsByTagName() method will return an HTMLCollection

const paraEl = document.getElementsByTagName('p');
console.log(paraEl);

// Use the index to get the last paragraph

let lastPara = paraEl[2];
console.log(lastPara);

// Use the length property

console.log(paraEl.length);

The JavaScript code above retrieves all <p> elements in the document using getElementsByTagName('p') and stores them in an HTMLCollection named paraEl. It then logs the HTMLCollection to the console. Next, it retrieves the third <p> element from the HTMLCollection using paraEl[2] and stores it in lastPara, then logs lastPara to the console.

Lastly, it logs the number of <p> elements in the HTMLCollection to the console using the length property in paraEl.length. A screenshot of the result is below.

Example of array-like behaviour and length property with NodeList:

// The querySelectorAll() method will return a Nodelist

let paraEl = document.querySelectorAll('p');
console.log(paraEl);

// Use the index to get the last paragraph

let lastPara = paraEl[2];
console.log(lastPara);

// Use the length property

console.log(paraEl.length);

The JavaScript code in the example above uses the querySelectorAll() method to select all the <p> elements in the document and stores them in a NodeList named paraEl. It then logs the NodeList to the console. Next, it retrieves the third <p> element from the NodeList using paraEl[2] and stores it in lastPara, then logs lastPara to the console.

Lastly, it logs the number of <p> elements in the NodeList to the console using the length property in paraEl.length. A screenshot of the result is below.

Differences between HTMLCollection and NodeList

HTMLCollection and NodeList have some key differences, which include the following:

1. Content

HTMLCollection is primarily focused on element nodes (e.g., <p>, <div>, <img>), and other elements nested within the HTML structure. NodeList covers a wider range of nodes, including element nodes (e.g., <p>, <div>, <img>), text nodes (actual text content within elements), and attribute nodes (attributes associated with elements, like href in an <a> tag).

Code example:

<div id="parent">
<p>This is a paragraph</p>
<span>This is a span</span>
This is a text node
</div>

The code example above is a <div> element with an id parent that contains a <p> element, a <span> element, and a text node (a piece of text not enclosed in an element). Both the <p> and <span> elements have text nodes inside them.

// Find the first <div> element in the HTML document
const divElement = document.querySelector('div');

// Print a message indicating that we're using the children method to get the child elements
console.log("HTML Collection using the children method:");

// Print the list of child elements (HTMLCollection) of the <div> element
console.log(divElement.children);

// Print a message indicating that we're going to print the text content of each child element
console.log("Content:");

// Loop through each child element and print its text content
for (let i = 0; i < divElement.children.length; i++) {
console.log(divElement.children[i].textContent);
}

// Print a message indicating that we're using the childNodes method to get all child nodes
console.log("Node List using the ChildNodes method:");

// Print the list of all child nodes (NodeList) of the <div> element
console.log(divElement.childNodes);

// Print a message indicating that we're going to print the text content of each child node
console.log("Content:");

// Loop through each child node and print its text content
for (let i = 0; i < divElement.childNodes.length; i++) {
console.log(divElement.childNodes[i].textContent);
}

The code example above retrieves a <div> element from the HTML document using document.querySelector() method. It then demonstrates the difference between children and childNodes properties of the element. Now, let me break it down in the following steps:

  1. divElement.children: This property returns an HTMLCollection containing only the element's child elements (i.e., the <p> and <span> elements excluding text nodes and comment nodes inside them). The code logs each child element's text content using a for loop.
  2. divElement.childNodes: This property returns a NodeList containing all the child nodes (i.e., the <p> and <span> elements including text nodes and comment nodes inside them). The code also logs the text content of each node using a for loop.
  3. The code uses console.log statements to print the contents of both collections. A screenshot of the result is below.

From the screenshot image of the code example above, you’ll see that the HTMLCollection obtained using the children property only includes the direct child elements of the <div> (i.e., the <p> and <span> elements), excluding any hidden text or comments. This is why it shows two items.

On the other hand, the NodeList obtained using the childNodes property includes all types of child nodes, such as elements, text nodes, and comments, that are direct children of the <div>. This is why it shows five items (i.e., the <p> and <span> elements, text nodes, and comments).

If you only want to get the element nodes inside a <div>, you can use the children property which returns an HTMLCollection containing only element nodes.

However, if you want all nodes, not just the element nodes that return a NodeList, you can get them all using the childNodes property.

2. Live Collections vs. Static Collections

The terms “live” and “static” in the context of HTMLCollection and NodeList describe how these collections behave when changes are made to the DOM. Here’s a breakdown:

An HTMLCollection is Always Live

In the live collection, the changes made to the underlying HTML document, such as adding, removing, or modifying elements, are automatically updated in the HTMLCollection.

Code example:

<div class="items">Item 1</div>
<div class="items">Item 2</div>
<div class="items">Item 3</div>

The code example above creates three <div> elements, each with the class "items" and containing text that indicates an item.

// Get all elements with the class "items" which returns an HTMLCollection
const items = document.getElementsByClassName('items');

// Log the initial length of the HTMLCollection
console.log('HTMLCOLLECTION INITIAL LENGTH BEFORE UPDATE: ', items.length); //Output: 3

//Returns an HTML Collection
console.log('HTMLCOLLECTION BEFORE UPDATE: ', items);

//Add a new div with a class of "items"
const newDiv = document.createElement('div');
newDiv.className = 'items'; // Set the class name for the new div

// Append the new div to the document body or another parent element
document.body.appendChild(newDiv);

// Log the final length of the HTMLCollection after the update
console.log('HTMLCOLLECTION FINAL LENGTH AFTER UPDATE: ', items.length); //Output: 4 (HTMLCollection is live and not affected by direct DOM manipulation)

console.log('HTMLCOLLECTION AFTER UPDATE: ', items);

The code example above retrieves all elements with the class “items” and stores them in an HTMLCollection called items. It then logs the initial length of the items collection. Next, it creates a new <div> element with the class "items" and appends it to the document body.

Finally, it logs the final length of the items collection, demonstrating that the HTMLCollection is live and reflects changes to the DOM. A screenshot of the result is below.

From the screenshot image of the code example above, you’ll see the HTMLCollection had three <div> elements before the update. But after the update, the HTMLCollection now has four <div> elements, reflecting the change in the document.

A NodeList is often Static

In the static collection, the changes made to the underlying HTML document, such as adding, removing, or modifying elements, are not automatically updated in the NodeList.

Code example:

<div class="items">Item 1</div>
<div class="items">Item 2</div>
<div class="items">Item 3</div>

The code example above creates three <div> elements, each with the class "items" and containing text that indicates an item.

// Get all elements with the class "items" which returns a NodeList
const divs = document.querySelectorAll('div');

// Log the initial length of the NodeList
console.log('NODELIST INITIAL LENGTH BEFORE UPDATE: ', divs.length); //Output: 3

//Returns a NodeList
console.log('NODELIST BEFORE UPDATE: ', divs);

//Add a new div with a class of "items"
const newDiv = document.createElement('div');
newDiv.className = 'items'; // Set the class name for the new div

// Append the new div to the document body or another parent element
document.body.appendChild(newDiv);

// Log the final length of the NodeList after the update
console.log('NODELIST FINAL LENGTH AFTER UPDATE: ', divs.length); //Output: 3 (NodeList is static and not automatically updated when the DOM is manipulated directly)

console.log('NODELIST AFTER UPDATE: ', divs);

The code example above retrieves all <div> elements in the document using document.querySelectorAll('div') and stores them in a NodeList called divs. It then logs the initial length of the NodeList. Next, it creates a new <div> element with the class "items" and appends it to the document body.

Finally, it logs the final length of the NodeList, showing that the NodeList is static and does not automatically update to reflect the new element added to the DOM. It’s important to note that the NodeList (divs) does not automatically update when the DOM is manipulated directly, so the final length of the NodeList will remain the same as the initial length. A screenshot of the result is below.

From the screenshot image of the code example above, you’ll see that the NodeList had three<div> elements before the update. But after the update, the NodeList still has three <div> elements, reflecting no change in the document.

Note: In the live collection, the changes made to the underlying HTML document, such as adding, removing, or modifying elements, are automatically updated in the NodeList re-querying the DOM.

To get the updated length of the NodeList after adding a new element for instance, you need to re-query the DOM using document.querySelectorAll('div') or a similar method. Since NodeList is static and does not update automatically, re-querying the DOM will give you a new NodeList that includes the newly added element.

Code example:

<div class="items">Item 1</div>
<div class="items">Item 2</div>
<div class="items">Item 3</div>

The code example above creates three <div> elements, each with the class "items" and containing text that indicates an item.

// Get all elements with the class "items" which returns a NodeList
let divs = document.querySelectorAll('div');

// Log the initial length of the NodeList
console.log('NODELIST INITIAL LENGTH BEFORE UPDATE: ', divs.length); //Output: 3

//Returns a NodeList
console.log('NODELIST BEFORE UPDATE: ', divs);

//Add a new div with a class of "items"
const newDiv = document.createElement('div');

newDiv.className = 'items'; // Set the class name for the new div

// Append the new div to the document body or another parent element
document.body.appendChild(newDiv);

// Re-query the DOM to get the updated NodeList
divs = document.querySelectorAll('div');

// Log the final length of the NodeList after the update
console.log('NODELIST FINAL LENGTH AFTER UPDATE AND RE-QUERYING: ', divs.length); //Output: 4

console.log('NODELIST AFTER UPDATE AND RE-QUERYING: ', divs);

In this code, we first obtain a NodeList of all <div> elements in the document and log its initial length. We then add a new <div> element to the document, append it to the body, and re-query the document to get the updated NodeList. Finally, we log the updated length of the NodeList and the NodeList itself before and after the update.

This approach demonstrates how to effectively work with NodeList and re-query the DOM to reflect changes made to the document. A screenshot of the result is below.

From the screenshot image of the code example above, you’ll see that the NodeList had three<div> elements before the update. But after re-querying the DOM, the NodeList now have four <div> elements, reflecting the change in the document.

3. Accessing Elements

An HTMLCollection is accessed by index number (starting from 0) and additionally allows accessing elements by their ID or name if they are unique, while a NodeList is also accessed by index number (starting from 0) but does not allow accessing elements by ID or name.

4. Obtaining

An HTMLCollection is typically obtained using methods like getElementsByTagName(tagName) or getElementsByClassName(className) to select elements by tag name or class name.

A NodeList is typically obtained using querySelectorAll(selector) to select elements or by accessing the childNodes() property of an element, which returns all child nodes, including text and attribute nodes.

Choosing the Right Tool

HTMLCollection

Use HTMLCollection when you need to manipulate specific groups of HTML elements and want a collection that reflects dynamic changes to the DOM.

NodeList

Use NodeList when you need to access a broader representation of the DOM structure at a specific point in time, including text and attribute nodes, and it doesn’t require live updates.

Conclusion

While both collections are array-like and used for DOM manipulation, understanding their differences in content, live vs. static behaviour, accessing methods, and obtaining mechanisms are crucial for selecting the appropriate tool for your specific needs.

However, it is important to understand their differences in terms of content, live versus static behaviour, access methods, and retrieval mechanisms to choose the most suitable tool for your particular requirements.

If you find this article helpful, please consider clapping, sharing, and following me for more front-end development tips and tricks! Thank you for your support! 🙌

--

--

Coinmonks
Coinmonks

Published in Coinmonks

Coinmonks is a non-profit Crypto Educational Publication.

Wasiu Akindoyin
Wasiu Akindoyin

Written by Wasiu Akindoyin

Web3 Technical Writer | Front-end Developer | Simplifying complex Web3 and software concepts through code and real-life analogies.