Higher Order Functions no JavaScript
Aprenda a manipular Arrays com a mágica das HOF
Grande parte das pessoas que começam na programação sentem dificuldades em manipular estruturas como os Arrays. Começamos utilizando aqueles maravilhosos for, while e do while, mas no final o código fica parecendo a pia de casa depois de um jantar em família, e nem te conto quem vai ter que lavar tudo depois 😢.
Por esse motivo, hoje vim aqui te apresentar as queridinhas dos desenvolvedores JavaScript, as Higher Order Functions. As HOF são definidas como funções que aceitam funções como parâmetro e/ou retorna a função como saída.
🤔 Ficou meio confuso? 🤔 Vou te mostrar alguns exemplos e te garanto que vai ficar mais nítido.
As HOF que iremos ver nesse artigo são:
- Array.prototype.find
- Array.prototype.filter
- Array.prototype.forEach
- Array.prototype.map
- Array.prototype.reduce
1- Array.prototype.find
Digamos que nós temos um array com os valores: 10, 15, 20, 25 e 30, e queremos selecionar o primeiro número maior que vinte. Uma maneira de fazermos isso é com o seguinte código:
Entretanto o método find simplifica nossa vida, ele retorna o valor do primeiro elemento do array que atender a função de teste fornecida como argumento, e caso não encontre nenhum resultado, o valor retornado é undefined. Bora para um exemplo:
No exemplo exemplo acima, é criado um array contendo os números: 10, 15, 20, 25, 30. Logo em seguida, nossa intenção é capturar o primeiro elemento maior que 20, então utilizamos o método find.
A linha 3 pode ser lida da seguinte forma, percorra cada elemento do array, e retorne o primeiro elemento maior que vinte.
A arrow funtion passada como argumento para o método find vai ser executada para cada elemento do array, verificando se ele atende a expressão de teste elemento > 20, se o resultado for verdadeiro, o elemento é retornado.
Na linha 5, ao imprimirmos a variável maiorQueVinte obteremos o valor 25.
Não é necessário passar arrow funcitons como argumentos dos métodos mostrados aqui, podemos utilizar uma função normal, como no exemplo a seguir:
Podemos perceber que ao invés de escrevermos uma arrow function como argumento, declaramos uma função chamada callback que recebe um elemento, e essa função é passado como argumento no find. Por preferência, todos os demais exemplos serão mostrados utilizando arrow functions.
2- Array.prototype.filter
Alterando um pouco o exemplo anterior, agora temos um array com os mesmo valores e queremos selecionar todos os números maiores que vinte. Uma maneira de fazermos isso é com o seguinte código:
Entretanto, o método filter simplifica muito a escrita desta operação, ele retorna um novo array com todos os elementos que satisfaçam a expressão de teste fornecida como argumento, e caso não encontre nenhum resultado, o valor retornado é undefined. Bora para um exemplo:
Agora utilizando o método filter para obtermos todos os elementos maiores que 20.
A linha 3 pode ser lida como, percorra cada elemento do array e nos retorne todos os elementos maiores que vinte.
A arrow funtion passada como argumento para o método filter vai ser executada para cada elemento do array, verificando se o elemento atende a expressão de teste elemento > 20, se o resultado for verdadeiro o elemento fará parte do array retornado.
Na linha 5, ao imprimirmos a variável maioresQueVinte obteremos o array contendo 25 e 30.
Dica: Outra ótima aplicação do método filter é para remover elementos indesejados de um array, por exemplo:
Agora queremos todos os elementos do array inicial exceto o 20.
Utilizando o filter e fornecendo a arrow function com a expressão de teste elemento !== 20, a função irá nos retornar um array com todos os elementos iniciais e irá excluir o 20 do resultado. Lembrando que o filter não altera o array original, ele gera um novo array como resultado.
3- Array.prototype.forEach
Agora queremos imprimir uma mensagem personalizada para cada elemento do nosso array no padrão array[ index ] = elemento. Uma maneira de fazermos isso é com o seguinte código:
Outro ponto que iremos abordar aqui, e que não é exclusivo do forEach, são os parâmetros opcionais fornecido para a callback . Nos exemplos anteriores, a callback recebia apenas o elemento atual do array, entretanto existem os parâmetros opcionais index e array:
- elemento: O valor atual do elemento sendo processado no array.
- index (opcional): O índice do elemento atual sendo processado no array.
- array (opcional): O array em que o forEach está sendo aplicado.
Tendo isso em mente, o método forEach executa uma dada função em cada elemento de um array e diferente das funções anteriores, o forEach não possui um retorno. Preste muita atenção nessa parte do retorno, se tentarmos armazenar o resultado do forEach em uma variável, receberemos somente o valor undefined. Bora para um exemplo:
Agora utilizando o método forEach para imprimirmos nossas mensagens personalizadas.
A linha 3 pode ser lida como, percorra cada elemento do array e imprima a mensagem no padrão array[ index ] = elemento.
A arrow funtion passada como argumento para o método forEach, além de receber elemento também recebe o index e vai ser executada para cada elemento do array imprimindo a mensagem que informamos.
Ao executarmos a Linha 3, o resultado obtido é o código comentado.
4- Array.prototype.map
Continuando nosso exemplo das mensagens personalizadas, mas ao invés de imprimirmos cada mensagem, agora queremos salvar todas elas em um array. Uma maneira de fazermos isso é com o seguinte código:
Outra maneira de realizar esse tipo de operação é utilizando o método map, ele executa a função callback passada por argumento para cada elemento do array e devolve um novo array como resultado. Bora pro exemplo:
Agora utilizando o método map para criarmos nossos array de mensagens personalizadas.
A linha 3 pode ser lida como, percorra cada elemento do array e armazene o retorno da arrow function no array resultante, no caso o retorno é a mensagem no padrão array[ index ] = elemento.
E ao executarmos a Linha 5, o resultado obtido é o código comentado, um array com todas as mensagens.
5- Array.prototype.reduce
E para fecharmos com chave de ouro, agora teremos um array com os valores: 1, 2 e 3, e queremos obter a soma de todos os elementos desse array. Uma maneira de fazermos isso é com o seguinte código:
Uma forma mais simples de realizar essa mesma operação é com o reduce, ele executa uma função reducer (fornecida por você) para cada elemento do array, resultando em um único valor de retorno.
O reduce possui uma pequena diferença em relação ao métodos que vimos anteriormente, a callback que ele recebe possui como primeiro argumento um acumulador.
O acumulador irá acumular o retorno de cada iteração sobre o array. Execute o código abaixo e tudo ficará mais nítido.
O acumulador começa com o valor 1 e o elementoAtual começa com o valor 2, pois eles são o primeiro e segundo elemento do array respectivamente.
Na segunda interação o acumulador passa a valer 3, pois é a soma de 1 + 2. Já o elementoAtual também vale 3, pois é o valor do terceiro elemento do array.
Ao imprimirmos a soma total na linha 10, obtemos o valor 6, pois foi a ultima operação realizada no reduce, somando 3 + 3.
Um último ponto, e se quisermos que o acumulador não comece com o valor do elemento inicial do array? Podemos fazer isso adicionando um argumento com o valor inicial do acumulador após a callback, veja o exemplo:
No código acima, acumulador começa com o valor 3 e o elementoAtual começa com o valor 1, pois ele possuirá o valor do primeiro elemento do array e o acumulador será iniciado com o valor que informamos, no caso 3.
Na segunda interação o acumulador passa a valer 4, pois é a soma de 3 + 1. Já o elementoAtual vale 2, pois é o valor do segundo elemento do array.
Na terceira interação o acumulador passa a valer 6, pois é a soma de 4 + 2. Já o elementoAtual vale 3, pois é o valor do terceiro elemento do array.
Ao imprimirmos a soma total na linha 8, obtemos o valor 9, pois foi a ultima operação realizada no reduce, somando 6+ 3.
Conclusão
Foi bastante coisa né pessoal? Peguem todos esses códigos que foram passados aqui e executem nas suas máquinas, modifiquem, busquem exercícios e aprendam. Uma dica de ouro, dominem as Higher Order Functions, pois elas vão facilitar muito a sua vida e tornar seu código muito mais limpo.
Referências
- Documentação Array.prototype.find()
- Documentação Array.prototype.filter()
- Documentação Array.prototype.forEach()
- Documentação Array.prototype.map()
- Documentação Array.prototype.reduce()