Net Propaganda 🔍
Net Propaganda
Editorias
Institucional
Apps e Software

Closure JavaScript: o que é e como usar

Closure em JavaScript é um comportamento fundamental que permite a uma função acessar variáveis do escopo onde ela foi criada, mesmo depois que esse escopo já terminou de executar. Na prática, quando uma função é definida dentro de outra, ela "lembra" do ambiente léxico ao redor, o que inclui variáveis locais, parâmetros e até funções declaradas no escopo externo. Esse mecanismo é usado em padrões como módulos, contadores e funções de fábrica, mas exige cuidado com o ciclo de vida das variáveis e com o consumo de memória.

O que é closure em JavaScript?

Closure é a combinação de uma função com as referências ao estado que a circunda, ou seja, o ambiente léxico. Quando você declara uma função dentro de outra, a função interna não apenas executa seu próprio corpo, mas também carrega consigo o escopo da função externa. Isso significa que, mesmo após a função externa retornar, a função interna ainda consegue acessar e manipular as variáveis daquele escopo. Um exemplo clássico é o contador privado:

function contador() { let valor = 0; return function() { valor++; return valor; }; }

const incrementar = contador(); console.log(incrementar()); // 1 console.log(incrementar()); // 2

Aqui, a função anônima retornada mantém acesso à variável valor, mesmo depois que contador() foi executada. Essa persistência é o que caracteriza uma closure.

Como o escopo léxico se relaciona com closure?

O escopo léxico define quais variáveis uma função pode acessar com base na sua posição no código, não no momento da chamada. Em JavaScript, toda função tem acesso ao escopo onde foi declarada, e não ao escopo onde foi invocada. A closure explora exatamente essa característica: a função interna "enxerga" as variáveis do escopo externo porque esse escopo faz parte do seu ambiente léxico. Isso é diferente de linguagens como C ou Java, onde o escopo é determinado em tempo de execução, sem esse tipo de memória persistente.

Um ponto de atenção: o escopo léxico é estático, mas as variáveis são dinâmicas. Ou seja, a closure acessa o valor atual da variável, não uma cópia do valor no momento da criação. Se a variável for alterada depois, a closure verá o valor atualizado.

Por que closures são úteis no dia a dia?

Closures resolvem problemas práticos de encapsulamento e estado. Elas permitem criar variáveis privadas, algo que JavaScript não tem nativamente. Em vez de expor uma variável global, você pode criar uma função que retorna funções com acesso controlado a um estado interno. Isso é comum em módulos, onde se quer esconder detalhes de implementação. Closures também são a base para funções de alta ordem, como map, filter e reduce, que recebem funções como argumento e muitas vezes precisam "capturar" valores do escopo externo.

Outro uso frequente é em eventos e callbacks. Quando você registra um callback que precisa acessar dados de um loop, a closure preserva o valor correto de cada iteração, desde que você use let ou crie um novo escopo a cada iteração.

Quais são os riscos e cuidados ao usar closures?

O principal risco é o consumo de memória. Cada closure mantém viva a referência ao escopo externo, mesmo que a função externa já tenha retornado. Se você criar muitas closures em um loop, por exemplo, pode manter objetos desnecessários em memória, prejudicando a performance. Outro cuidado é com o valor de variáveis em loops. Se você usar var dentro de um loop, a closure captura a mesma variável para todas as iterações, resultando em valores inesperados. Com let, cada iteração recebe um novo escopo, resolvendo o problema.

Um contraexemplo comum:

for (var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); // 3, 3, 3 }, 100); }

Com var, todas as closures compartilham a mesma variável i, então ao final do loop o valor é 3. Usar let corrige o comportamento.

Como usar closures em funções de fábrica e módulos?

Funções de fábrica são funções que retornam outras funções com comportamento personalizado. Closures permitem que cada função retornada tenha seu próprio estado. Por exemplo:

function criarSaudacao(saudacao) { return function(nome) { return ${saudacao}, ${nome}!; }; }

const ola = criarSaudacao('Olá'); const tchau = criarSaudacao('Tchau'); console.log(ola('Maria')); // Olá, Maria! console.log(tchau('João')); // Tchau, João!

No padrão módulo, closures ajudam a criar APIs públicas com estado privado. A variável saudacao fica inacessível fora da closure, mas é usada internamente.

Closure e o padrão módulo em JavaScript

O padrão módulo utiliza closures para encapsular dados e expor apenas métodos públicos. Um exemplo:

const contadorModulo = (function() { let valor = 0; return { incrementar: function() { valor++; }, obter: function() { return valor; } }; })();

contadorModulo.incrementar(); console.log(contadorModulo.obter()); // 1

Aqui, valor não é acessível diretamente, apenas através das funções retornadas. Isso protege o estado interno e evita alterações acidentais.

Como closures afetam o desempenho da aplicação?

Closures não são intrinsecamente lentas, mas cada closure adiciona uma camada de referência ao escopo externo. Em aplicações pequenas, o impacto é desprezível. Em loops com milhares de iterações, criar closures desnecessárias pode aumentar o uso de memória e o tempo de garbage collection. A recomendação é usar closures quando há necessidade real de capturar escopo, e evitar em operações de alta frequência sem motivo. Medir com ferramentas de profiling é sempre mais confiável do que presumir gargalos.

Qual a diferença entre closure e função normal?

Uma função normal, sem closure, acessa apenas seu próprio escopo e o escopo global. Uma closure, por outro lado, acessa também o escopo da função onde foi declarada, mesmo após essa função ter retornado. Na prática, toda função em JavaScript pode se tornar uma closure se for declarada dentro de outra e referenciar variáveis externas. A diferença está na persistência do ambiente léxico, que é o que permite o acesso posterior.

Como resolver problemas clássicos com closures?

Um problema clássico é o loop com var e setTimeout. A solução mais direta é substituir var por let, criando um novo escopo a cada iteração. Outra solução é usar uma IIFE (Immediately Invoked Function Expression) para capturar o valor atual:

for (var i = 0; i < 3; i++) { (function(indice) { setTimeout(function() { console.log(indice); // 0, 1, 2 }, 100); })(i); }

Essa abordagem é útil em código legado ou quando você não pode alterar a declaração da variável.

Resumo: quando usar closure com segurança?

Use closures para encapsular estado, criar funções de fábrica e implementar módulos. Evite em loops sem necessidade e em funções chamadas milhares de vezes por segundo. Sempre prefira let ou const em escopos de bloco para evitar compartilhamento de variáveis. Teste o consumo de memória em aplicações grandes.

Perguntas frequentes sobre closure em JavaScript

O que é closure em JavaScript com exemplo?

Closure é quando uma função interna acessa variáveis da função externa mesmo depois que ela terminou. Exemplo: uma função que retorna outra função e essa função interna usa uma variável do escopo externo.

Qual a diferença entre closure e escopo em JavaScript?

Escopo define quais variáveis são acessíveis em cada parte do código. Closure é um mecanismo que permite a uma função acessar o escopo externo mesmo após a execução da função externa. Todo closure envolve escopo, mas nem todo escopo gera closure.

Como closures podem causar vazamento de memória?

Se uma closure mantém referência a um objeto grande que não é mais necessário, esse objeto não será coletado pelo garbage collector enquanto a closure existir. Isso pode aumentar o uso de memória em aplicações de longa duração.

Por que usar let em vez de var em closures?

let cria um novo escopo a cada iteração de loop, então cada closure captura o valor correto da variável. var compartilha o mesmo escopo em todo o loop, fazendo todas as closures verem o valor final.

É possível criar closure sem uma função interna?

Não. Closure é definida pela combinação de uma função com seu ambiente léxico. Sem uma função interna, não há como capturar o escopo externo de forma persistente.

Como closures são usadas em React ou Node.js?

Em React, closures aparecem em hooks como useState e useEffect, que capturam estado e props. Em Node.js, closures são comuns em callbacks e middlewares, preservando dados de requisições em funções assíncronas.

Ptolomeu Rangel Sicupira
Pesquisador de tendências e cultura digital
Lê a internet como antropólogo; conecta meme, comportamento e estratégia de marca.
Ver todos os artigos →