Antes de dar uma definição formal, vamos entender onde elas podem ser úteis e por que usá-las.
Em um certo sistema, diversas operações de divisão de arrays são necessárias.
Essa é uma das maneiras de implementar essas operações:
const copyArrayAndDivideBy2 = (arr) => {
const result = []
for(let i = 0; i < arr.length; i++) {
result.push(arr[i] / 2)
}
return result
}
const copyArrayAndDivideBy3 = (arr) => {
const result = []
for(let i = 0; i < arr.length; i++) {
result.push(arr[i] / 3)
}
return result
}
Obviamente essa solução é péssima, praticamente todo o código é repetido, bugs conseguem se esconder facilmente e se caso a lógica mude, alguém vai precisar encontrar todas as funções e alterar uma por uma. Existem várias soluções melhores pra esse problema e uma delas é utilizar funções de ordem superior, que é o que vamos fazer a seguir.
O que são funções de ordem superior?
Uma função de ordem superior, ou higher order function (HOF), como vamos chama-la, é uma função que recebe como argumento, ou retorna uma função. Isso é possível porque em Javascript, funções são entidades de primeira classe, ou seja, é possível passar elas como argumentos para uma outra função.
Mas por que HOFs são importantes? Elas são ótimas ferramentas para evitar repetição desnecessária e seguir princípios como o DRY e KISS.
Como usar em Javascript
Vamos continuar o exemplo anterior, refatorando aquelas funções para uma HOF.
Aqui, toda a parte de copiar o array e iterar sobre ele é separada da lógica, que vai ser passada como argumento quando essa função for chamada.
const copyArrayAndManipulate = (arr, instructions) => {
// o parâmetro `instructions` normalmente é chamado de `callback`
// ele deve ser uma funcao que contém toda a lógica de manipulação
// do elemento, antes dele ser copiado para o resultado.
const result = []
for(let i = 0; i < arr.length; i++) {
result.push(instructions(arr[i])
}
return result
}
Agora conseguimos utilizar essa função para fazer o mesmo que antes, mas evitando repetição de código.
const divideBy2 = (input) => input / 2
const arrayDividedBy2 = copyArrayAndManipulate([2, 4, 6], divideBy2) // [1, 2, 3]
Simplificando ainda mais a implementação, podemos refatorar ela novamente:
const arrayDividedBy2 = copyArrayAndManipulate(
[2, 4, 6],
(input) => input / 2
) // [1, 2, 3]
Espero que agora tenha ficado muito mais claro onde usar essas funções
HOFs na biblioteca padrão do Javascript
A função copyArrayAndManipulate
é muito parecida com uma padrão da linguagem, a Array.forEach
e isso não é coincidência, HOFs são utilizadas múltiplas vezes nas funções padrões do JS.
Podemos implementar uma versão mais simples do Array.forEach
com os conceitos que aprendemos nesse artigo, que funciona de uma forma muito similar a original.
// recebe como parâmetro um array para iterar
// e uma função com a lógica a ser executada
const iterateOver = (array, callback) => {
let i = 0, len = array.length
while(i < len) {
const value = array[i]
// executar a função passada por quem está chamando a função
// e passar como argumento o elemento atual do array e o índice dele
callback(value, i)
i++
}
}
// chamando a função definida anteriormente e passando uma função
// de callback que imprime os elementos do array junto com o índice deles
iterateOver([1, 2, 3], (a, i) => {
console.log(`elemento: ${a}, índice: ${i}`)
})
/* output
> elemento: 1, índice: 0
> elemento: 2, índice: 1
> elemento: 3, índice: 2
*/
Conclusão
Funções de ordem superior são uma ferramenta extremamente útil para o dia a dia, elas são utilizadas em diversos lugares nas funções embutidas no JS e em outras bibliotecas, porém, o conceito pode ser um pouco difícil de se entender, se algo não ficou claro, por favor entre em contato comigo!
Referências
https://eloquentjavascript.net/05_higher_order.html
https://frontendmasters.com/courses/javascript-hard-parts-v2/
Top comments (0)