This post seeks to provide an overview of the differences between these collection types, and some guidance on working with them.
Let's first shed light on what we mean by Application Programming Interfaces (APIs). What APIs do is abstract complex code away. They are constructs baked into programs that provide an easy way for you to create complex functionality, without exposing you to the hairiness of the complete code base.
This metaphor found on the MDN site is quite illustrative:
As a real-world example, think about the electricity supply in your house, apartment, or other dwellings. If you want to use an appliance in your house, you simply plug it into a plug socket and it works. You don't try to wire it directly into the power supply — to do so would be really inefficient and, if you are not an electrician, difficult and dangerous to attempt.
The point being: if you want to do something relatively complex, such as 3D graphics, you don't have to reinvent the wheel. Instead, you can leverage existing, ready-to-use APIs for your needs.
And that's what an API is in essence - an 'Interface' (a layer between two things) between a complete codebase and your program, enabling you to create stuff on top of existing functionality with ease.
These browser APIs fall into two categories:
HTMLCollection, on the other hand, are web APIs belonging to the browser. They are included in the HTML specification rather than ECMAScript.
So methods such as
Why does this matter? It matters because the API for each collection type specifies the methods available to it and the type of data elements it can contain.
Let's have a look at the difference between them.
HTMLCollection, both interfaces are lists of DOM nodes.
HTMLCollection is the older one of the two, which the W3 docs describe as:
a historical artifact we cannot rid the web of.
It was used prior to the modern DOM, and is only included in the DOM specification to show how browsers used to work before it.
The two are essentially very similar, but differ in:
HTMLCollectionprovides the same methods as a
NodeListand additionally a method called
NodeListcan contain any node type, an
HTMLCollectionis supposed to only contain Element nodes.
💡Note - Difference between a node and an element: A node refers to any DOM object (e.g. document node), whereas an element is a specific type of node (e.g. div node). As such, every element is a node, but not every node is an element.
Let's illustrate the differences using an example. Say we have a list with some list items:
<ul> <!-- List items --> <li>List item 1</li> <li>List item 2</li> <li>List item 3</li> <li>List item 4</li> <li>List item 5</li> </ul>
ourList = document.querySelector('ul'); // retrieves our list console.log(ourList.childNodes); // all of the list's children that are nodes console.log(ourList.children); // only the children that are elements
This is what the console would output for the code above:
The NodeList contains all of the unordered lists' children nodes. Since nodes are elements and more, this includes all the elements (in this case, list items only), whitespace and comments. The HTML collection only holds children elements.
What's important to keep in mind is that these different types of objects (NodeLists and arrays) have their own methods and properties associated with them. That's the differentiator.
Returning to the above example, say we wanted to get a list of all the list items and we wrote:
let ourList = document.querySelectorAll('li'); // NodeList stored in ourList variable
We now have a NodeList, but what if you have a need to use array methods such as
splice on the list - what to do?
Before we consider conversion, you can test to see what type of list you're dealing with.
console.log(Array.isArray(ourList)); // false or true console.log(ourList.constructor.name); // NodeList (if NodeList)
A NodeList can be converted to an Array in a few ways.
We can use one of the following methods:
ourList = Array.from(ourList) // returns an array from the list - simple, eh?
Array.prototype.slice.call(ourList) // returns a shallow copy of the origina in array form
If you are using ES6, you can use the spread operator
ourList = [...ourList]; // I like this one
Keep in mind that there are other ways in which the NodeLists and arrays differ, namely whether the lists are live or static - live meaning that when elements are removed/added to the DOM, the list updates automatically. For a static list that is not the case. According to the docs:
A collection can be either live or static. Unless otherwise stated, a collection must be live.
As in, the default case is a live collection. Here are the different options from a SO answer:
document.getElementsByClassName() retrieves a live HTMLCollection document.getElementsByTagName() also retrieves a live HTMLCollection document.getElementsByName() retrieves a live NodeList document.querySelectorAll() retrieves a static NodeList HTMLCollections appear to always be live
If you'd like to read more into the different browser APIs, check out the links below:
WEB APIs Reference - https://developer.mozilla.org/en-US/docs/Web/Reference/API