Map or Filter over HTMLCollection and NodeList in Javascript

You want to do something with HTML elements on the page and like to use map and filter. But map and filter do not work because collections returned by querySelectorAll or getElementsByName are not arrays.

The console keeps telling you .map() or .filter() is not a function but you don't understand why.

I also did not understand why map and filter did not work and since I was in a hurry I almost reverted back to looping over the collection.

But there is an easy solution to this problem. After reading this article you know how to convert an HTMLCollection and NodeList to an array so you can use Map and Filter on it.

Let’s start by making a page with three buttons on it:

<button id="button1">Button1</button>
<button id="button2">Button2</button>
<button id="button3">Button3</button>

Suppose your application wants to disable all buttons on the page:

disable buttons

The first thing we need to do is query the document for all the buttons:

const htmlButtons = document.querySelectorAll('button');
console.log(htmlButtons);

Which will give you a NodeList with three items:

NodeList(3) [button#button1, button#button2, button#button3]
0: button#button1
1: button#button2
2: button#button3
length: 3

You can read more about a NodeList in the documentation but for this article all you need to know is that a NodeList is not an array and you cannot use map and filter on it.

nodelist buttons

If you try to use the NodeList as an array, you get an error. We can test this by mapping the items and disable each one:

htmlButtons.map(button => button.disabled = true);

Output:

Uncaught TypeError: t.map is not a function

Solution: Convert NodeList to an array

To convert a NodeList or HTMLCollection to and array you use two features of javascript:

How does that work?

Here is an example of creating an array in Javascript:

const a = [1, 2];
console.log(a);

Output:

[ 1, 2 ]

Javascript took the two values and constructed an array from this. Here comes the interesting part: Let’s do the same but now you create an array from the old array and a new value:

const a = [1, 2];
b = [a, 3]
console.log(b);

Output:

[ [ 1, 2 ], 3 ]

As expected, a new array has been created and contains two items, one is an array, one is a number. But if you want an array with all numbers (1, 2 and 3) flattened out, you can do this with the spread operator:

const a = [1, 2];
c = [...a, 3]
console.log(c);

Output:

[ 1, 2, 3 ]

The spread operator unpacked the elements in array a. You can use this functionality to unpack the elements in a NodeList or HTMLCollection and create an array from it.

Use the spread operator to create an array from a NodeList or HTMLCollection

Here is the full code that you need to:

const htmlButtons = document.querySelectorAll('button');
const htmlButtonsArray = [...htmlButtons];
htmlButtonsArray.map(button => button.disabled = true);

Free free to compact the code to a one-liner in your programs.

I hope this helps you with the HTML elements on your pages. From now, you can stop looping over HTML elements and start using the spread operator to manipulate the elements on the page like a pro!

Written by Loek van den Ouweland on November 28, 2019. Questions regarding this artice? You can send them to the address below.
By using this site, you acknowledge that you have read and understand our Cookie and Privacy Policy.