Higher-Order Functions em JavaScript: map, filter, reduce e Composição na Prática Já leu

O que são Higher-Order Functions? Higher-Order Functions (HOF) são funções que recebem outras funções como argumentos ou retornam funções como resultado. Elas são fundamentais na programação funcional e permitem escrever código mais reutilizável, expressivo e modular. Em JavaScript, como tudo é um objeto — inclusive funções — trabalhar com HOF é natural e poderoso. O grande benefício é a abstração: em vez de escrever loops repetitivos, você descreve o que quer fazer com seus dados. Isso torna o código mais legível e menos propenso a erros. Vamos explorar as três HOFs mais importantes: , e . Map, Filter e Reduce na Prática Map: Transformar Dados aplica uma função a cada elemento de um array e retorna um novo array com os resultados. Use-o quando quiser transformar todos os itens de forma igual. Filter: Selecionar Dados cria um novo array contendo apenas os elementos que passam em um teste. Use-o para remover ou selecionar itens baseado em uma condição. Reduce: Agregar

O que são Higher-Order Functions?

Higher-Order Functions (HOF) são funções que recebem outras funções como argumentos ou retornam funções como resultado. Elas são fundamentais na programação funcional e permitem escrever código mais reutilizável, expressivo e modular. Em JavaScript, como tudo é um objeto — inclusive funções — trabalhar com HOF é natural e poderoso.

O grande benefício é a abstração: em vez de escrever loops repetitivos, você descreve o que quer fazer com seus dados. Isso torna o código mais legível e menos propenso a erros. Vamos explorar as três HOFs mais importantes: map, filter e reduce.

Map, Filter e Reduce na Prática

Map: Transformar Dados

Map aplica uma função a cada elemento de um array e retorna um novo array com os resultados. Use-o quando quiser transformar todos os itens de forma igual.

const numeros = [1, 2, 3, 4, 5];
const dobrados = numeros.map(n => n * 2);
console.log(dobrados); // [2, 4, 6, 8, 10]

// Exemplo real: converter objetos de uma API
const usuarios = [
  { id: 1, nome: "Ana" },
  { id: 2, nome: "Bruno" }
];
const nomes = usuarios.map(u => u.nome);
console.log(nomes); // ["Ana", "Bruno"]

Filter: Selecionar Dados

Filter cria um novo array contendo apenas os elementos que passam em um teste. Use-o para remover ou selecionar itens baseado em uma condição.

const numeros = [1, 2, 3, 4, 5, 6];
const pares = numeros.filter(n => n % 2 === 0);
console.log(pares); // [2, 4, 6]

// Exemplo real: listar apenas usuários ativos
const usuarios = [
  { id: 1, nome: "Ana", ativo: true },
  { id: 2, nome: "Bruno", ativo: false },
  { id: 3, nome: "Carlos", ativo: true }
];
const ativos = usuarios.filter(u => u.ativo);
console.log(ativos); // Ana e Carlos

Reduce: Agregar Dados

Reduce acumula valores em um único resultado, passando por cada elemento. Use-o para sumarizar dados: somas, contagens, agregações ou transformações complexas.

const numeros = [1, 2, 3, 4, 5];
const soma = numeros.reduce((acumulador, atual) => acumulador + atual, 0);
console.log(soma); // 15

// Exemplo real: contar ocorrências de palavras
const palavras = ["gato", "cão", "gato", "pato", "cão", "cão"];
const contagem = palavras.reduce((acc, palavra) => {
  acc[palavra] = (acc[palavra] || 0) + 1;
  return acc;
}, {});
console.log(contagem); // { gato: 2, cão: 3, pato: 1 }

Composição de Higher-Order Functions

Composição é combinar múltiplas funções pequenas para resolver problemas complexos. A beleza é que map, filter e reduce retornam arrays (ou valores), permitindo encadeamento natural.

const usuarios = [
  { id: 1, nome: "Ana", salario: 3000, ativo: true },
  { id: 2, nome: "Bruno", salario: 2500, ativo: false },
  { id: 3, nome: "Carlos", salario: 4000, ativo: true }
];

// Problema: somar salários apenas de usuários ativos
const totalAtivos = usuarios
  .filter(u => u.ativo)
  .map(u => u.salario)
  .reduce((acc, sal) => acc + sal, 0);

console.log(totalAtivos); // 7000 (Ana + Carlos)

Esse padrão é extremamente legível: filtro → extraio salários → somo. Para problemas ainda mais complexos, crie funções compostas reutilizáveis:

// Criar predicados e transformadores reutilizáveis
const ehAtivo = u => u.ativo;
const extrairSalario = u => u.salario;
const somar = (acc, val) => acc + val;

// Aplicar em qualquer contexto
const totalAtivos = usuarios
  .filter(ehAtivo)
  .map(extrairSalario)
  .reduce(somar, 0);

// Outra composição: média salarial
const quantidadeAtivos = usuarios.filter(ehAtivo).length;
const mediaAtivos = totalAtivos / quantidadeAtivos;
console.log(mediaAtivos); // 3500

Criando Funções Compostas Avançadas

Função Compose Genérica

Uma função compose recebe múltiplas funções e as aplica em sequência. Isso é programação funcional pura:

// Compose: aplica funções da direita para esquerda
const compose = (...funcs) => valor => 
  funcs.reduceRight((acc, func) => func(acc), valor);

// Funções básicas
const adicionar10 = x => x + 10;
const multiplicarPor2 = x => x * 2;
const dividirPor5 = x => x / 5;

// Compor: (((5 * 2) + 10) / 5)
const pipeline = compose(dividirPor5, adicionar10, multiplicarPor2);
console.log(pipeline(5)); // 4

// Pipe: aplica da esquerda para direita (mais intuitivo)
const pipe = (...funcs) => valor => 
  funcs.reduce((acc, func) => func(acc), valor);

const processamento = pipe(multiplicarPor2, adicionar10, dividirPor5);
console.log(processamento(5)); // 4

Exemplo Real: Processamento de Dados

const dados = [
  { nome: "Alice", idade: 25, ativo: true },
  { nome: "Bob", idade: 17, ativo: false },
  { nome: "Carol", idade: 30, ativo: true }
];

// Predicados e transformadores específicos
const maioresDeIdade = p => p.idade >= 18;
const ehAtivo = p => p.ativo;
const extrairNome = p => p.nome;

// Composição prática
const nomesMaioresEAtivos = dados
  .filter(maioresDeIdade)
  .filter(ehAtivo)
  .map(extrairNome);

console.log(nomesMaioresEAtivos); // ["Alice", "Carol"]

// Ou com um único filter (otimizado):
const nomesMaioresEAtivos2 = dados
  .filter(p => maioresDeIdade(p) && ehAtivo(p))
  .map(extrairNome);

Conclusão

Higher-Order Functions são pilares da programação moderna em JavaScript. Ao dominar map para transformações, filter para seleções e reduce para agregações, você escreve código declarativo e robusto. Composição de HOFs permite resolver problemas complexos de forma elegante e legível — é o caminho para se tornar um desenvolvedor mais eficiente. Pratique combinando essas funções em seus projetos reais e perceba como seu código fica mais profissional e manutenível.

Referências


Artigos relacionados