HTMLCollection Vs NodeList

Last modified on July 26th, 2022
Javascript

Learn the key differences between HTMLCollection and NodeList.

HTMLCollection is an array-like object that has a collection of document elements.

A NodeList object is a collection of document nodes (element nodes, attribute nodes, and text nodes).

1. Methods That Return HTMLCollection & NodeList

HTMLCollection

These two methods return the HTMLCollection object.

  1. getElementByTagName() and
  2. getElementsByClassName()

NodeList

Methods that return NodeList are:

  1. getElementsByName()
  2. querySelectorAll()

Try it out!

See the Pen 1 Methods That Return HTMLCollection & NodeList by SoftAuthor (@softauthor) on CodePen.

2. HTMLCollection (Element Nodes) vs NodeList (All Nodes)

HTMLCollection only contains element nodes such as <div>, <span>, etc.

NodeList contains element nodes, attribute nodes, text nodes, etc.

That’s kind of confusing…right.

Let’s take a look at this with a code example.

Here is the simple HTML markup.

It has a div with an id called box-wrapper which is the parent element.

The parent element has a text node and two element nodes.

<div id="box">
  I'm Text Node
  <div>I'm Element Node 1</div>
  <div>I'm Element Node 2</div>
</div>

Let’s see how to get the children of it.

To get only element nodes, use the .children property on the parent document object.

In this case: box.

The .children property returns the HTMLCollection which only contains element nodes.

In this case [div, div] but it ignores the text “I’m Text Node”

const box = document.getElementById("box");

// console.log(box.children); // HTMLCollection(2) [div, div]
// console.log(box.childNodes); // NodeList(5) [text, div, text, div, text]

On the other hand, the .childNodes property on the parent document object returns the NodeList that contains element nodes, attribute nodes, text nodes, etc.

Try it out!

See the Pen HTML Collection (Element Nodes) vs NodeList (All Nodes) by SoftAuthor (@softauthor) on CodePen.

3. HTMLCollection (name, id or index number) Vs NodeList (index only)

HTMLCollection items can be accessed by their name attribute, id attribute, or index number.

NodeList items can only be accessed by their index numbers.

HTMLCollection

In the below code example, get the first child div element inside the box-wrapper parent element.

<div id="box-wrapper">
  <div name="nm-box1" id="id-box1" class="cls-box1">box 1</div>
  <div name="box2">box 2</div>
  <div name="box3">box 3</div>
  <div>box 4</div>
</div>

To do that, convert the children of the box-wrapper parent element to HTMLCollection using the children property.

Use index number, id, or name attribute to get a specific item from the HTMLCollection using the namedItem() method.

const boxWrapper = document.getElementById('box-wrapper');
const boxes = boxWrapper.children; // HTMLCollection

console.log(boxes[0]); // Using Index WORKS!
console.log(boxes.namedItem("id-box1")); // Using ID WORKS!
console.log(boxes.namedItem("nm-box1")); // Using Name WORKS!
console.log(boxes.namedItem("cls-box1")); // Using Class NULL

NodeList

Convert the children of the box-wrapper parent element to NodeList using the .childNodes property.

When using NodeList, you can only get a specific item using its index position.

const boxWrapper = document.getElementById('box-wrapper');
const boxes = boxWrapper.childNodes; // NodeList

console.log(boxes[0]); // Using Index WORKS!
console.log(boxes.namedItem("id-box1")); // Using ID ERROR!
console.log(boxes.namedItem("nm-box1")); // Using Name ERROR!
console.log(boxes.namedItem("cls-box1")); // Using Class ERROR!

Try it out!

See the Pen HTML Collection (Name, Id and Index) vs NodeList (Only Index) by SoftAuthor (@softauthor) on CodePen.

4. HTMLCollection (live*) Vs NodeList (static*)

HTMLCollection

getElementByTagName() and getElementsByClassName() are live.

When an underlying document is changed, the HTMLCollection will be updated automatically.

Let’s see that in action.

I have a simple div element with an id box-wrapper and it has 4 child div elements inside.

Let’s add an element to it.

<div id="box-wrapper">
  <div class="box" name="box">box 1</div>
  <div class="box" name="box">box 2</div>
  <div class="box" name="box">box 3</div>
  <div class="box" name="box">box 4</div>
</div>

First, get all the div elements that have the .box class in it using getElementsByClassName() which returns the HTMLCollection.

At this stage, the HTMLCollection has 4 items in it.

Then, add a new div element with the class name .box to it.

Now, the HTMLCollection has five items in it.

const boxWrapper = document.getElementById("box-wrapper");

const boxes = boxWrapper.getElementsByClassName("box");
console.log(boxes.length); // 4

const div = document.createElement("div");
div.classList.add("box");
div.innerHTML = "box 5";
boxWrapper.appendChild(div);

console.log(boxes.length); // 5

Similarly, getElementsByTagName() method automatically returns the updated HTMLCollection when there is a change in the list.

There is one exception: Even though, getElementsByName() returns NodeList – but it’s LIVE.

NodeList

The NodeList that is returned by querySelectorAll() is NOT live.

When there is a change to the underlying document, it does not automatically update the NodeList.

Instead it will make a copy of the NodeList with a new element.

In order to get the updated NodeList, you’ll have to call the querySelectorAll() method again.

const boxes = document.querySelectorAll(".box");
console.log(boxes.length); // 4

const div = document.createElement("div");
div.setAttribute("class", "box");
div.innerHTML = "box 5";
boxWrapper.appendChild(div);

console.log(boxes.length); // 4
console.log(document.querySelectorAll(".box").length); // 5

Try it out!

See the Pen HTMLCollection (live) Vs NodeList (static) by SoftAuthor (@softauthor) on CodePen.

5. HTMLCollection (for..of) Vs NodeList (forEach)

All recent versions of modern browsers (Safari, Firefox, Chrome, Edge) all support for/of iteration on DOM lists such nodeList or HTMLCollection.

HTMLCollection

HTMLCollection is an array-like object that can be iterated using the for..of method.

<div class="box">box 1</div>
<div class="box">box 2</div>
<div class="box">box 3</div>
<div class="box">box 4</div>
<div class="box">box 5</div>
const boxes = document.getElementsByClassName("box"); //HTMLCollection

for(box of boxes) {
  console.log(box); // [HTMLDivElement]
}

It does not have forEach() method on it.

In order to use forEach() method, you’ll have to convert the HTMLCollection into an array.

const boxes = document.getElementsByClassName("box"); //HTMLCollection

const boxesArray = Array.from(boxes);

boxesArray.forEach(box => {
  console.log(box); // [HTMLDivElement]
})

NodeList

Unlike the HTMLCollection, NodeList has a forEach() method natively.

const boxes = document.querySelectorAll(".box"); //NodeList

boxesArray.forEach(box => {
  console.log(box); // [HTMLDivElement]
})