Menu

Métodos de Array em JavaScript: map, filter, reduce e cia

Os métodos de array que substituem a maioria dos seus loops for — map, filter, reduce, find, some e every — e quais deles alteram o array original ou devolvem um novo.

Esta página tem editores executáveis — edite, execute e veja a saída na hora.

Arrays vêm com uma caixa de ferramentas

Os arrays em JavaScript trazem um conjunto enorme de métodos prontos. Quase tudo que você faria com um for — transformar valores, escolher alguns, somar o total — tem um método que resolve em uma linha, lê melhor e ainda combina bem com os outros.

O kit inicial são três métodos: map, filter e reduce. Domine esses três, mais alguns primos próximos, e aquele seu código cheio de loops vira algo que dá pra entender de bate-pronto.

Cada método recebe um callback e devolve algum resultado. Repare que nenhum deles alterou nums — vale a pena gravar isso bem cedo.

map: transformando cada elemento do array

O array map em JavaScript recebe uma função e a executa em cada elemento, juntando os valores retornados num novo array do mesmo tamanho. Use quando você quer "uma saída para cada entrada".

O callback também recebe o índice como segundo argumento, caso você precise: arr.map((item, i) => ...). Quando não precisar, é só ignorar.

Um erro clássico: usar map quando você não precisa do array retornado. Se a ideia é só imprimir cada item ou salvar no banco, o certo é forEach ou um loop comum.

filter: mantendo só o que interessa

O filter executa um predicado — uma função que devolve true ou false — em cada elemento e mantém os que retornarem um valor "truthy". O array resultante tem o mesmo tamanho do original ou menos.

map e filter encaixam naturalmente em cadeia. Leia a sequência da esquerda para a direita como um pipeline:

Filtre primeiro e só depois faça o map — assim o map roda apenas sobre os que sobreviveram.

reduce: reduzindo um array a um único valor

O reduce é o mais versátil dos três. Você passa uma função redutora no formato (acumulador, item) => novoAcumulador e um valor inicial. Ele percorre o array, entrega cada item para o redutor junto com o acumulador atual e, no final, devolve o valor em que o acumulador terminou.

O resultado não precisa ser um número. Pode ser um objeto, outro array, uma string — qualquer coisa que você queira construir:

Sempre passe o valor inicial (o segundo argumento). Sem ele, o reduce usa o primeiro elemento como acumulador inicial, o que quebra em arrays vazios e, na maioria das vezes, nem é o comportamento que você queria.

O reduce é poderoso, mas fica difícil de ler quando a lógica começa a embolar. Se o seu reducer passa de umas poucas linhas, um for...of tradicional costuma ser bem mais claro.

forEach: efeitos colaterais, sem retorno

O forEach é tipo um map que não devolve array. Ele serve pra quando você quer fazer alguma coisa com cada item — dar um log, chamar uma API, atualizar o DOM — sem precisar gerar uma nova coleção.

Duas coisas importantes para saber:

  • forEach retorna undefined. Ou seja, não dá pra encadear um .map() depois.
  • Também não dá pra sair do forEach antes da hora com break. Se você precisar interromper no meio, use for...of ou some/every.

Se você se pegar escrevendo arr.forEach(x => results.push(transform(x))), isso é um map disfarçado.

find e findIndex: só um elemento, por favor

O find devolve o primeiro elemento que satisfaz a condição, ou undefined caso nenhum bata. Já o findIndex devolve o índice desse elemento (ou -1 se não achar nada).

find para no primeiro resultado que bate com a condição. Evite filter(...)[0] — isso varre o array inteiro só pra descartar o resto.

some e every: perguntas que retornam booleano

O some retorna true se pelo menos um elemento passar no teste. Já o every só retorna true quando todos passam.

Os dois fazem short-circuit — o some para na primeira ocorrência true, e o every para no primeiro false. São a ferramenta certa para responder perguntas do tipo "tem algum...?" / "todos são...?".

slice vs splice: copiar ou cortar

Os nomes são parecidos, mas o comportamento é bem diferente.

O slice(start, end) devolve uma cópia rasa de um trecho do array, sem mexer no original. O end é exclusivo; se você omitir, ele vai até o final.

splice(start, deleteCount, ...items) altera o array no lugar. Ele remove deleteCount elementos a partir da posição start, opcionalmente insere novos itens e retorna os elementos removidos.

Mnemônico: slice é seguro (copia), enquanto splice faz cirurgia direto no array original.

Métodos que mutam vs métodos que não mutam

Essa diferença faz toda a diferença no dia a dia. Código que altera sem querer um array compartilhado é um dos bugs mais chatos de rastrear.

Mutam (alteram o original e geralmente retornam outra coisa):

  • push, pop, shift, unshift
  • splice, sort, reverse
  • fill, copyWithin

Não mutam (retornam um novo array ou valor, sem mexer no original):

  • map, filter, slice, concat
  • flat, flatMap
  • find, findIndex, some, every, includes, indexOf
  • reduce, reduceRight

Os dois traiçoeiros são sort e reverse — parecem inofensivos e mutam o array sem avisar. Se você quer uma cópia ordenada, faça um slice antes:

O JavaScript moderno também traz as versões que não mutam o array: toSorted, toReversed, toSpliced e with. Elas devolvem um novo array e deixam o original intacto. Já funcionam em todos os runtimes atuais — então, sempre que puder, prefira essas.

flat e flatMap

O flat achata arrays aninhados em um nível (ou mais, se você passar a profundidade como argumento). Já o flatMap é um map seguido de um flat de um nível — bem útil quando cada item gera zero ou mais saídas.

flatMap é a forma elegante de "expandir" itens — uma entrada, várias saídas — sem precisar recorrer a um flat() depois.

Juntando tudo na prática

Um exemplo pequeno e realista. Dada uma lista de pedidos, calcule a receita total dos pedidos concluídos acima de R$ 50:

Três métodos, um pipeline, zero controle manual de loop. Cada etapa já diz o que faz. Dá pra fundir os dois filter em um só, mas separar fica legível — e às vezes ajuda bastante na hora de debugar.

A seguir: Map e Set

Arrays dão conta muito bem de sequências ordenadas, mas ficam desajeitados quando você precisa de busca rápida por chave ou de uma coleção de valores únicos. O JavaScript tem duas estruturas de dados nativas justamente pra esses casos — Map e Set — e é esse o tema da próxima página.

Perguntas frequentes

Qual a diferença entre map, filter e reduce em JavaScript?

map transforma cada elemento e devolve um novo array do mesmo tamanho. filter mantém só os elementos que passam no teste e devolve um novo array (geralmente menor). Já reduce percorre o array e reduz tudo a um único valor — pode ser uma soma, um objeto, outro array, o que você quiser construir.

Qual a diferença entre forEach e map?

forEach executa uma função para cada elemento e retorna undefined — é pensado para efeitos colaterais. Já map executa a função em cada elemento e devolve um novo array com os resultados. Se você quer um array transformado, use map. Se só precisa fazer algo por elemento e não liga pro resultado, use forEach (ou um for...of).

Quais métodos de array mutam o array original?

Os que mutam são push, pop, shift, unshift, splice, sort, reverse, fill e copyWithin. O resto — map, filter, slice, concat, flat, flatMap, find, some, every e reduce — não mexe no array original e devolve um valor novo.

Quando usar slice e quando usar splice?

slice(start, end) devolve uma cópia rasa de um trecho do array sem mexer no original. Já splice(start, deleteCount, ...items) muta o array — remove e/ou insere elementos no lugar e devolve os que foram removidos. Para lembrar: slice é seguro, splice faz cirurgia no array.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR