Se você em algum momento precisou manipular e iterar vários itens no DOM, é bem provável que já tenha se deparado com uma NodeList.
Como informado na documentação da MDN, os objetos NodeLists
são coleções de nós similares aos objetos retornados de métodos como Node.childNodes
e document.querySelectorAll()
.
Sendo assim, é bem comum uma criarmos pequena confusão de que NodeLists são iteráveis como arrays:
const anchors = document.querySelectorAll('a');
Array.isArray(anchors) // false
Uma NodeList não sendo um array, logo os métodos de um array não funcionam numa NodeList:
anchors.map(i => console.log(i));
// Uncaught TypeError: anchors.map is not a function
Aqui apresento algumas diferentes abordagens de como converter NodeLists em arrays iteráveis.
for
O bom e velho for
sempre funciona, bom para usar quando precisa dar suporte em navegadores muito antigos:
var anchors = document.querySelectorAll('a');
var arrayOfAnchors = [];
for (var i = 0; i < anchors.length; i++) {
var item = anchors[i];
arrayOfAnchors.push(item);
}
Array.prototype.slice.call()
Uma outra abordagem afim de garantir suporte em navegadores mais antigos como é o caso do IE10 e IE11, para não precisar utilizar nenhum tipo de polyfill, pode ser uma boa usar o Array.prototype.slice.call()
:
const arrayOfAnchors = Array.prototype.slice.call(anchors);
Array.isArray(arrayOfAnchors); // true
// ou
const arrayOfAnchors = [].slice.call(anchors);
Array.isArray(arrayOfAnchors); // true
forEach()
O forEach
é um dos métodos disponíveis dentro de uma NodeList:
anchors.forEach(i => console.log(i))
Na MDN é explicado de maneira bem sucinta o uso do forEach()
em uma NodeList. Contudo, pode ser um problema caso seja necessário suportar navegadores mais antigos como o caso do IE10, por exemplo:
Apesar de NodeList não ser um Array, é possível ser iterada usando o método forEach(). Muitos navegadores antigos ainda não implementaram este método
Suporte dos navegadores: https://caniuse.com/?search=forEach
for…of
Também é possível obter um array de uma NodeList utlizando o for...of
:
const anchors = document.querySelectorAll('a');
let arrayOfAnchors = [];
for (item of anchors) {
let item = anchors[i];
arrayOfAnchors.push(item);
}
Suporte dos navegadores: https://caniuse.com/?search=for…of
Array.from()
Agora, se você não precisa lidar com browsers mais antigos, com a vinda do ES6 alguns anos atrás, ficou bem simples converter NodeLists em arrays. Basta usar o Array.from()
:
Array.from(anchors).map(i => console.log(i));
O Array.from()
permite que você crie arrays à partir de objetos array-like e Objetos iteráveis, como o Map e o Set.
Suporte dos navegadores: https://caniuse.com/?search=array%20from
Spread Operator
Mais um caminho via ES6, utilizando o spread operator:
const anchors = [...document.querySelectorAll('a')];
Array.isArray(anchors) // true
Suporte dos navegadores: https://caniuse.com/?search=spread%20operator
Conclusão
Existem diversas formas de converter uma NodeList num array para facilitar sua manipulacão no DOM. A escolha delas vai depender de alguns fatores como suporte aos navegadores, uso de polyfills para alguns métodos, se sua aplicação utiliza transpilers que garantam o uso de ES6+ e coisas do gênero.