You will be able to select elements with query methods, inspect the returned NodeList, and safely loop over or convert it when you need array methods.
What it is
A NodeList is an ordered, array-like collection of DOM nodes returned by some query methods. The most common example is document.querySelectorAll("li"), which returns every matching element in document order. A NodeList is not an Array, but it has length, indexed access, and iterable methods such as forEach.
Related terms: static NodeList (a snapshot, like querySelectorAll), live NodeList (updates with the DOM, like childNodes), and HTMLCollection (another DOM collection type).
Why it matters
- It lets you update many elements at once, such as list items, buttons, or table rows.
- It shows the exact order of elements in the document.
- It helps you avoid errors by knowing when to convert to an array.
- It clarifies whether a collection will change after you create it.
Syntax or steps
The smallest useful pattern is:
const nodes = document.querySelectorAll("selector");
nodes.length;
nodes.forEach((node) => {
// use node
});
If you need array methods, convert it:
const array = Array.from(nodes);
Example
This example assumes the page contains several li elements.
const items = document.querySelectorAll("li");
console.log(items.length);
items.forEach((item, index) => {
item.textContent = `${index + 1}. ${item.textContent}`;
});
const texts = Array.from(items).map((item) => item.textContent);
console.log(texts);
Part-by-part
document.querySelectorAll("li")returns a static NodeList of all matching elements.items.lengthreports how many nodes were found.items.forEachloops over each element without converting to an array.Array.from(items)creates a real array somapcan be used.
Common mistakes
- Calling array methods directly.
items.map()fails because NodeList is not an array. UseArray.from(items).map(). - Expecting live updates. A NodeList from
querySelectorAlldoes not include elements added later. Query again if needed. - Confusing NodeList with HTMLCollection.
childNodescan include text nodes, whilequerySelectorAllreturns elements. Usechildrenfor element-only live collections. - Ignoring empty results. If no elements match,
lengthis0andforEachdoes nothing. Checklengthwhen needed.
When to use it
| Need | Use | Why |
|---|---|---|
| Result of a CSS selector query | querySelectorAll() NodeList | Static, iterable, and element-only. |
Array methods like filter or reduce | Array.from(nodeList) | Gives a real array. |
| Live element children | element.children HTMLCollection | Updates automatically and contains only elements. |
| All child nodes, including text | element.childNodes NodeList | Includes text and comment nodes. |
Practice
Guided exercise
Select all paragraphs, add the class highlight, and log the count.
const paragraphs = document.querySelectorAll("p");
paragraphs.forEach((p) => p.classList.add("highlight"));
console.log(paragraphs.length);
Challenge
Convert a NodeList of list items to an array and keep only items whose text includes "done".
Hint: Use Array.from(items).filter((item) => item.textContent.includes("done")).
Quick check
If you run document.querySelectorAll("li"), then add a new li to the page, does the NodeList include the new item?
No. The NodeList from querySelectorAll is static, so it keeps the snapshot taken when the query ran.
Summary
NodeLists are the normal result of DOM queries: ordered, iterable, and array-like, but not arrays. Use them directly for simple loops, and convert them when you need full array behavior.