map(), filter() e reduce() em JavaScript

Saiba mais sobre map(), filter() e reduce() e como usar estas importantes funções de programação funcional em JavaScript.

Ir para o artigo

Já alguns anos, JavaScript chegou com métodos de manipulação de array mais voltados à programação funcional. Neste artigo, conheça a utilidade das funções map(), filter() e reduce() através de exemplos de códigos, parâmetros e casos de uso.

Como programadores, construímos e manipulamos arrays de números, strings, booleanos e objetos quase todos os dias. Nós os usamos para processar números, coletar objetos, dar split em string, pesquisar, ordenar e muito mais. Mas qual é a melhor maneira de trabalhar com arrays? Tradicionalmente, tem sido usar loops para fazer a iteração nos elementos usando índice.

Em 2011, chegou em JavaScript map(), filter() e reduce() como alternativas poderosas tanto para se trabalhar com valores cumulativos, quanto para criar subconjuntos com base em condições. Estes métodos são úteis para reduzir a complexidade, trabalhar sem “efeitos colaterais” e, muitas vezes, tornar o código mais legível.

Desvantagens do loop

Digamos que se está trabalhando em uma correção de bug e, vagueando por 1000 linhas de código JavaScript, eis que o seguinte loop se apresenta:

Foi possível ver que o loop serve para criar um novo array com elementos não duplicados no original. Mas, para descobrir isso, foi necessária uma análise em 5 etapas:

Código Significado
var i = 0 Começa à esquerda do array
i < array.length Termina à direita
i++ Incremento de 1 em 1
array.indexOf( array[ i ] ) === i Se o valor é de primeira instância no array, vai coincidir com o índice (isso significa que se está verificando uma duplicata)
models.push(...) models deve ser uma lista, mas quais dados ali constam? Quais são seus tipos de dados? É preciso procurar um arquivo “models”. Enxaguar. Repetir.

É necessário verificar 5 pedaços de informações para determinar o que está acontecendo. E este é um único loop!

Uma abordagem funcional

Este mesmo objetivo poderia ser escrito usando o método filter() de JavaScript da seguinte maneira:

Simples e elegante.

Visto que filter() comunica comportamento de código, então é possível saber exatamente o objetivo da função. Em comparação com a abordagem de looping acima:

  • Checar #1, #2 e #3 é desnecessário, já que filter() faz isso automaticamente.
  • #4 é o mesmo, mas sem o adicional de checagem do bloco if.
  • Um grande obstáculo foi #5 — lembra-se do número de questões que ele suscitava? map(), filter() e reduce() resolvem esse tipo de problema ao não dependerem de código fora dos callbacks.

No final das contas, map(), filter() e reduce() fazem do código menos complexo, sem efeitos colaterais e, freqüentemente, mais legível.

map()



Use map() quando: é preciso traduzir/mapear todos os elementos em um array para outro conjunto de valores.

Exemplo: converter temperatura de Fahrenheit para Celsius.

O que map() faz: percorre o array da esquerda para a direita invocando uma função de retorno em cada elemento com parâmetros. Para cada chamada de retorno, o valor devolvido se torna o elemento do novo array. Depois que todos os elementos foram percorridos, map() retorna o novo array com todos os elementos “traduzidos”.

Parâmetros:

Parâmetro Significado
elem Valor do elemento
index Índice em cada iteração, da esquerda para a direita
array Array original invocando o método
thisArg (opcional) Objeto que será referenciado como this no callback

filter()



Use filter() quando: é preciso remover elementos indesejados com base em alguma(s) condição(ões).

Exemplo: remover elementos duplicados de um array.

O que filter() faz: como map(), filter() percorre o array da esquerda para a direita invocando uma função de retorno em cada elemento. O valor retornado deve ser um booleano que indica se o elemento será mantido ou descartado. Depois de todos os elementos terem sido analisados, filter() retorna um novo array com todos os elementos que retornaram como verdadeiro.

Parâmetros (os mesmo que map()):

Parâmetro Significado
elem Valor do elemento
index Índice em cada iteração, da esquerda para a direita
array Array original invocando o método
thisArg (opcional) Objeto que será referenciado como this no callback

reduce()



Use reduce() quando: é preciso encontrar um valor cumulativo ou concatenado com base em elementos de todo o array.

Exemplo: soma de lançamentos de foguetes orbitais no período de 1 ano.

O que reduce() faz: como map(), reduce() percorre o array da esquerda para a direita invocando uma função de retorno em cada elemento. O valor retornado é o valor acumulado passado de callback para callback. Depois de todos os elementos terem sido avaliados, reduce() retorna o valor acumulado/concatenado.

Parâmetros:

Parâmetro Significado
prevVal Valor cumulado retornado em cada iteração
elem Valor do elemento
index Índice em cada iteração, da esquerda para a direita
array Array original invocando o método
initialValue (opcional) Objeto usado como primeiro argumento na primeira iteração (mais à esquerda)

Conclusão sobre map(), filter() e reduce() em JavaScript

Como informações extras sobre map(), filter() e reduce(), dá-se que:

  • Cada um deles é um método no objeto de protótipo (prototype) Array
  • Alterar um elemento no parâmetro array em qualquer callback persistirá através de todos os callbacks restantes, mas não apresentará quaisquer efeitos no array retornado
  • Funções de callback são invocadas nos índices com qualquer valor, até undefined, mas não valores excluídos ou que nunca tiveram um valor atribuído

Importante ressaltar, também, que map(), filter() e reduce() não vieram para substituir loops que, definitivamente, ainda têm seu lugar em diversas situações — como, por exemplo, ao se trabalhar com grandes arrays (mais de 1k elementos) ou quando é preciso parar a iteração se determinada(s) condição(ões) for(em) atendida(s) (break).

Para continuar a conhecer as principais funções de array JavaScript, leia também nosso artigo every(), some(), find() e includes() em JavaScript.

Usamos cookies para melhorar sua experiência e para ajudar a entender como nosso site é usado. Ao utilizar este site, você aceita o uso de cookies. Consulte nossa política de privacidade para obter mais informações.