Programação Funcional em JavaScript: Fundamentos e Prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à Programação Funcional em JavaScript



Programação Funcional (PF) é um paradigma de programação onde os cálculos são tratados como aplicação de funções matemáticas. Diferente da abordagem imperativa, onde escrevemos uma sequência de instruções que alteram o estado do programa, o estilo funcional foca no que precisa ser calculado, e não como fazer isso.



JavaScript, sendo uma linguagem multiparadigma, é excelente para programação funcional. No ambiente Node.js, essa abordagem é especialmente útil no processamento de dados, trabalho com streams e construção de aplicações server-side confiáveis. Neste artigo, vamos explorar os conceitos-chave da PF com exemplos práticos.



Princípios Fundamentais da Programação Funcional



Funções Puras (Pure Functions)

Uma função pura é uma função que:

  • Sempre retorna o mesmo resultado para os mesmos argumentos (determinismo).
  • Não possui efeitos colaterais (não altera variáveis externas, não imprime no console, não escreve em arquivos).


// Função puraconst add = (a, b) => a + b;

// Função impura (efeito colateral — saída no console)const impureAdd = (a, b) => { console.log(`Somando ${a} e ${b}`); return a + b;};

// Função impura (depende de estado externo)let counter = 0;const increment = () => ++counter;


Vantagens das funções puras: são fáceis de testar, depurar e paralelizar. Elas são previsíveis e não dependem do contexto de execução.



Imutabilidade (Immutability)

Imutabilidade significa que os dados, após criados, não são alterados. Em vez de modificar um objeto existente, criamos uma nova cópia dele com as alterações desejadas.



// Abordagem mutável (ruim)const user = { name: 'João', age: 30 };user.age = 31; // Alterando diretamente

// Abordagem imutável (boa)const user2 = { name: 'Maria', age: 25 };const updatedUser = { ...user2, age: 26 };// O objeto original user2 permanece inalterado

// Trabalhando com arraysconst numbers = [1, 2, 3];const newNumbers = [...numbers, 4]; // [1, 2, 3, 4]// numbers permanece [1, 2, 3]


Em Node.js, a imutabilidade é especialmente importante ao trabalhar com requisições e estado da aplicação, para evitar mutações inesperadas em código assíncrono.



Funções de Alta Ordem e Closures



Funções de Alta Ordem (Higher-Order Functions)

São funções que recebem outras funções como argumentos ou as retornam. Os métodos nativos de array map, filter, reduce são exemplos clássicos.



const numbers = [1, 2, 3, 4, 5];

// map — transforma cada elementoconst doubled = numbers.map(n => n * 2);// [2, 4, 6, 8, 10]

// filter — mantém elementos que satisfazem a condiçãoconst evens = numbers.filter(n => n % 2 === 0);// [2, 4]

// reduce — reduz o array a um único valorconst sum = numbers.reduce((acc, n) => acc + n, 0);// 15


Closures

Closure é uma função que "lembra" as variáveis do escopo onde foi criada, mesmo após esse escopo ter terminado sua execução.



const createCounter = () => {    let count = 0; // Variável privada    return () => ++count;};

const counter1 = createCounter();console.log(counter1()); // 1console.log(counter1()); // 2

const counter2 = createCounter();console.log(counter2()); // 1 (contador independente)


Closures são amplamente utilizados para criar fábricas de funções e encapsular estado no estilo funcional.



Currying e Composição de Funções



Currying

Currying é a transformação de uma função que recebe múltiplos argumentos em uma sequência de funções, cada uma

Blogs

Book Recommendations