HTMLCollection Or NodeList?
Open the project folder
In our starter files, open the index.html page from this lessons folder:
04.Events-And-The-DOM > 15.HTML-collection-or-NodeList
Example
Earlier in this section, we collected DOM elements using different methods, such as by class name, ID, and query selector.
When we selected multiple elements at once, we got back either a HTMLCollection or a NodeList. And, as promised earlier, we are now going to look at the difference between the two.
It often does not matter which one we have. Both contain multiple values in an array-like format which we can use how we want to, such as looping over them.
But if you are interested in the differences, we are going to cover them now. Over to the starter file, the index page has an unordered list:
<ul>
<li class="list-item">item1</li>
<li class="list-item">item2</li>
<li class="list-item">item3</li>
<li class="active">item4</li>
</ul>
Notice here the first three items have a class of list-item, and the last one is active. This will become important soon.
In the script.js we begin by selecting the list items we want in two different ways:
// script.js
// static
const static = document.querySelectorAll('.list-item');
// live
const live = document.getElementsByClassName('list-item');
Return values
The querySelectorAll method will return a NodeList and getElementsByClassName will return a HTMLCollection.
Which we can see with a console log:
console.log(static); //NodeList(3) [li.list-item, li.list-item, li.list-item]
console.log(live); // HTMLCollection(3) [li.list-item, li.list-item, li.list-item]
The length property
With both the NodeList and the HTMLCollection, first we have some similarities. They both have a length property:
console.log(static.length);
console.log(live.length);
And we can access single items by the index number:
console.log(static[2]);
console.log(live[2]);
Differences
There are also some key differences. Earlier we talked about Nodes and that we can have different types in the DOM. There are element nodes, attribute nodes, and text nodes. These are all values which can be returned with a NodeList.
However, with a HTMLCollection, it can only contain HTML elements. Often this is not going to cause us any problems, but it can be useful to know.
Static vs live
Another big difference is these comments at the top of the page, and the matching variable names:
// static
const static = document.querySelectorAll('.list-item');
// live
const live = document.getElementsByClassName('list-item');
A NodeList selected with querySelectorAll is static, and a HTMLCollection is live. This means when we update the DOM, only a live collection is aware of the changes.
Dynamically updating values
Let's see this by adding a new class to the list, we can then see which of our variables is updated.
In the index page, we can update the DOM by giving this fourth list item the same class of list-item dynamically using JavaScript, and see which one is updated:
<ul>
<li class="list-item">item1</li>
<li class="list-item">item2</li>
<li class="list-item">item3</li>
<li class="active">item4</li>
</ul>
In the script, select the list item with the class of active:
// static
const static = document.querySelectorAll('.list-item');
// live
const live = document.getElementsByClassName('list-item');
const active = document.querySelector('.active');
When showing multiple console logs like this, it can be more readable to wrap them in the curly braces:
console.log({static});
console.log({live});
This will display the result as an object, using the variable name as the property, then the contents as the value. Now when we read the log in the console, we have a label to identify each one:
{static: NodeList(3)}
{live: HTMLCollection(3)}
Next, set up a timer to add the class of list-item after three seconds so we can see what happens:
// bottom of script.js
setTimeout(function() {
active.classList.add('list-item')
console.log({static});
console.log({live});
}, 3000)
After this has been added, we again do a console log of our live and static lists to see which one has updated In the console, after three seconds we will see this:
{static: NodeList(3)} // initial static log
{live: HTMLCollection(3)} // initial live log
{static: NodeList(3)} // static still has 3 values after update
{live: HTMLCollection(4)} // live detects the update and now has 4 values
Only the live HTMLCollection is aware of the update, and now has the four items.
The static list has not changed, and the DOM will not be updated with the new values.