NodeList: Iterating and Converting DOM ResultsA JavaScript NodeList is an array-like collection of DOM nodes returned by document.querySelectorAll() and element.childNodes. Unlike HTMLCollection, a NodeList returned by querySelectorAll() is static and provides a built-in .forEach() method.
NodeList vs. Live childNodesBe aware of which method created the NodeList:
querySelectorAll(): Returns a static NodeList containing Element nodes only. Later DOM additions or removals do not alter this list.element.childNodes: Returns a live NodeList containing all node types, including Element tags, Text whitespace nodes, and HTML comments.NodeList for map(), filter(), and reduce()Although NodeList supports .forEach(), .entries(), and for...of, it still lacks array methods like .map(), .filter(), and .some(). Spreading [...nodeList] or calling Array.from(nodeList) converts it into a full JavaScript array in one step.
const app = document.getElementById("app");
if (app) {
app.innerHTML = `
<label><input type="checkbox" value="html" checked /> HTML</label>
<label><input type="checkbox" value="css" /> CSS</label>
<label><input type="checkbox" value="js" checked /> JS</label>
`;
const boxes = app.querySelectorAll('input[type="checkbox"]');
console.log("Total checkboxes (NodeList):", boxes.length);
// Convert NodeList to Array to chain filter() and map()
const selected = [...boxes]
.filter((box) => box.checked)
.map((box) => box.value);
console.log("Checked values:", selected);
}
document.querySelectorAll("p").map(...) directly: NodeList does not have .map() on its prototype, throwing TypeError: ...map is not a function. Spread into [...list] first.querySelectorAll() to update after inserting new elements: Because querySelectorAll() is static, run it again after appending new matching items.childNodes when you only want HTML tags: childNodes includes line-break text nodes; use element.children or element.querySelectorAll() for tags only.querySelectorAll() return if nothing matches the selector?It returns an empty NodeList with .length === 0—never null. Calling .forEach() on an empty NodeList safely runs zero times without throwing errors.
Array.from(nodeList) or [...nodeList] better?Both produce an identical standard array; [...nodeList] is concise, while Array.from(nodeList, el => el.textContent) lets you convert and map in a single pass.
NodeList support negative indexing like nodeList.at(-1)?No, NodeList does not implement .at(); read the last node with nodeList[nodeList.length - 1] or [...nodeList].at(-1).
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.