6 métodos importantes em Arrays de JavaScript

Explicando reduce, map, filter, find, every e some

Julio Betta
Oct 7, 2017 · 5 min read

Ultimamente, muito se tem falado em programação funcional e suas vantagens. Algumas linguagens com foco puramente funcional, como Haskell e Erlang, estão recebendo bastante atenção. Entretanto, suas técnicas e estilo podem ser utilizados na maioria das linguagens, como no nosso bom e velho amigo JavaScript (ok vai, nem tão velho assim…). Não entrarei em detalhes sobre programação funcional, pois já existe uma penca de artigos falando sobre isso.

O principal conceito utilizado será high-order function, que é basicamente uma função que recebe uma ou mais funções como argumentos ou retorna uma função. Neste artigo mostrarei como utilizar a high-order functionreduce e outras 5 variações, como map, filter, some, every e o find. Com “variações” quero dizer que todos estes métodos são, de algum modo, derivados do reduce, pois ele é capaz de fazer tudo o que estes outros fazem.

Uma característica marcante destes métodos que vale a pena ser citada é que elas não modificam o valor original da variável, seguindo uma outra característica importante da programação funcional: imutabilidade.

Nota: os códigos foram escritos na sintaxe ES6.


Mas afinal, do que o reduce é capaz?

O reduce é um método de Array.prototype, (assim como todos os outros citados acima) e sua função é transformar ou reduzir (sacou? reduzir, reduce…) os valores do array a um valor diferente do original.

Somando elementos de um array

O primeiro argumento do reduce é uma função (por isso é uma high-order function) que recebe como argumentos um acumulador, que agrega o resultado das iterações anteriores, e o item atual do array.
O segundo argumento é o valor inicial do acumulador, que neste caso é 0. É este argumento que define qual é o tipo do valor retornado, no caso um número inteiro.

Este foi um exemplo bem simples… afinal, não é todo dia que você precisa somar um array com 5 elementos, certo? Aguenta aí, pois nos próximos tópicos veremos como utilizar cada um das variações citadas e como seria sua versão com o reduce, que geralmente é mais verbosa.

Nota: O array abaixo (personagens de vídeo game e suas respectivas datas de estreia) será utilizado nos próximos exemplos.

const characters = [
{ name: "Donkey Kong", debut: 1981 },
{ name: "Captain Falcon", debut: 1990 },
{ name: "Fox", debut: 1993, },
{ name: "Kirby", debut: 1992 },
{ name: "Link", debut: 1986 }
];

.filter()

Como o próprio nome diz, este método é utilizado para filtrar os elementos de um array através de uma condicional executada dentro da função fornecida como argumento.

Filtrando personagens que estrearam antes de 1990

Note no exemplo acima como o métodofilter exige somente que seu primeiro argumento seja uma função, que retorna o resultado de uma expressão condicional, enquanto que na versão com reduce é necessário que deixemos explícito que, quando a condicional for verdadeira, o item atual da iteração seja adicionado ao acumulador. O resultado é o mesmo, porém filter é muito mais expressivo!

.map()

O map é um reprodutor de arrays adulteradas! Seu resultado é sempre um array com o mesmo tamanho do original, mas com pequenas (ou grandes) transformações.

Criando um novo array com o nome dos personagens

Novamente, é importante notar como as variações são bem mais expressivas que sua versão com reduce. No exemplo acima, a propriedade name foi extraída do objeto de cada elemento, resultando em um array diferente do original.

.some()

Em algum momento você já precisou verificar se, no seu array, existe pelo menos um elemento que cumpra uma condição. Geralmente, o primeiro impulso é usar filter e verificar se o tamanho do array resultante é maior que 0, como no código abaixo.

Utilizando filter para verificar se existe pelo menos 1 estreante antes de 1990

É exatamente para este tipo de situação que some existe. Ele elimina a necessidade de utilizar filter e esta verificação do tamanho do array resultante.

Qualquer semelhança com o filter não é mera coincidência. A diferença é o tipo de retorno, que neste caso é um boolean.

.every()

Bastante parecido com seu primo some, só que mais exigente. Oevery requer que todos os elementos do array cumpram com sua condição.

Oi?!

Algumas coisas diferentes estão acontecendo no código acima. Na linha 1, a função hasDebutAfter1980 será reaproveitada no resto do código para verificar se a estreia do personagem foi depois de 1980. E na linha 3, é utilizada como argumento para o every. Da mesma forma, nas linhas 6 e 10 para verificar a data de estreia do personagem da iteração atual dentro do reduce.

.find()

Eu costumo pensar que o find é um filter preguiçoso… ele busca por um elemento de acordo com a condição, e o primeiro encontrado já é retornado e pronto: missão cumprida.

Utilizando find para encontrar o primeiro personagem com estreia após 1980

Observe que, apesar de todos os personagens terem sua data de estreia após 1980, somente o primeiro é retornado.

Unindo forças

Como foi dito anteriormente, os métodos citados nos tópicos acima fazem parte de Array.prototype, portanto eles sempre estarão disponíveis numa variável do tipo Array. Repare que as funções filter e map sempre retornam um array, fazendo com que seja possível um encadeamento de métodos (method chaining).

Nome dos personagens que estrearam nos anos 90

Obviamente que o mesmo resultado pode ser obtido utilizando reduce, mas na minha humilde opinião, a combinação de métodos torna o código mais legível e incentiva a modularização, tornando-o mais fácil de ser reaproveitado e testado.

Modularização e legibilidade

No exemplo acima, a implementação da função que verifica se o personagem estreou nos anos 90 e a que extrai o nome do personagem foram atribuídas a uma variável e passadas como argumento para o filter e o map, respectivamente, e utilizadas separadamente em outros contextos.

A combinação destes métodos (não somente de filter e map) é realmente bastante poderosa!


Conclusão

Entender como extrair a informação correta ou manipulá-la de acordo com o contexto de sua aplicação é extremamente importante quando se lida, por exemplo, com ferramentas de visualização de dados, ou extrair somente uma parte da informação retornada por uma API. No mundo real, nem sempre estes dados estarão bem estruturados ou num formato amigável. Por este motivo é importante que nosso código seja o mais claro e legível possível, e com a ajuda dos métodos citados neste artigo fica mais fácil alcançar este objetivo. Nada contra for e forEach, mas chega de usá-los pra tudo nessa vida! ;)

Julio Betta

Written by

Software Developer @datagenno

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade