How to convert NodeLists in arrays
Tags: javascript, webdev
Published: 2020-10-21 11:17:05

If you have ever had to manipulate and iterate several items in the DOM, you probably already encountered a <b>NodeList</b>.
As reported in the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/NodeList), `NodeLists` objects are collections of nodes similar to objects returned from methods such as `Node.childNodes` and `document.querySelectorAll()`. <br />
Therefore, it is quite common to create a little confusion that NodeLists are iterable as arrays:

```javascript
const anchors = document.querySelectorAll('a');
Array.isArray(anchors) // false
```

As a NodeList is not an array, so arrays methods do not work on a NodeList:

```javascript
anchors.map(i => console.log(i));
// Uncaught TypeError: anchors.map is not a function
```
Here I present some different approaches on how to convert NodeLists into iterable arrays.

### for

The good old `for` always works, good to use when you need to support very old browsers:

```javascript
for (var i = 0; i < anchors.length; i++) {
  var item = anchors[i];
  console.log(item);
}
```

### Array.prototype.slice.call()

Another approach in order to guarantee support in older browsers such as IE10 and IE11, so as not to need to use any type of polyfill, it may be a good idea to use  `Array.prototype.slice.call()`:

```javascript
const arrayOfAnchors = Array.prototype.slice.call(anchors);
Array.isArray(arrayOfAnchors); // true

// or

const arrayOfAnchors = [].slice.call(anchors);
Array.isArray(arrayOfAnchors); // true
```

### forEach()

`ForEach` is one of the methods available within a NodeList:

```javascript
anchors.forEach(i => console.log(i))
```

In [MDN](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) the use of `forEach ()` in a NodeList is explained very succinctly. However, it can be a problem if it is necessary to support older browsers such as IE10, for example:

> Although NodeList is not an Array, it is possible to iterate using the `forEach()` method. Many older browsers have not yet implemented this method

Browser support: https://caniuse.com/?search=forEach

### for...of

It is also possible obtain an array of a NodeList from `for...of`:

```javascript
const anchors = document.querySelectorAll('a');
let arrayOfAnchors = [];

for (item of anchors) {
  let item = anchors[i];
  arrayOfAnchors.push(item);
}
```

Browser support: https://caniuse.com/?search=for...of

### Array.from()

Now, if you don't have to deal with older browsers, with the arrival of ES6 a few years ago, it became very simple to convert NodeLists into arrays. Just use `Array.from()`:

```javascript
Array.from(anchors).map(i => console.log(i));
```
The `Array.from()` method allows you to create arrays from array-like objects and [Iterable Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), like  [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and  [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).

Browser support: https://caniuse.com/?search=array%20from

### Spread Operator

Another ES6 way using the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator):

```javascript
const anchors = [...document.querySelectorAll('a')];
Array.isArray(anchors) // true
```

Browser support: https://caniuse.com/?search=spread%20operator

## Conclusion

There are several ways to convert a NodeList into an array to facilitate its manipulation in the DOM. Their choice will depend on some factors such as support for browsers, the use of polyfills for some methods, if your application uses transpilers that guarantee the use of ES6 + and something like that.