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:

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.

Se ficou com dúvidas na notação de rockets, leia o artigo sobre JSON.

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:

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).

Caso tenha dúvidas sobre a sintaxe de ECMAScript 6, conheça o repo es6features, com resumo das principais funcionalidades de ES6 com exemplos de códigos.