Lexical Environment Explicado
Profile picture

Junior Alves

Senior Developer

Foto: Unsplash

Atualizado: 3 de julho de 2025 às 08:58

Leitura: 7 minutos de leitura

Criado: 3 de julho de 2025

Lexical Environment Explicado

Seu código React e Node.js depende disso (e você precisa entender)

Introdução

Bora falar de um código que, muito provavelmente, você já escreveu ou viu dezenas de vezes? Imagine a cena: você está criando uma lista dinâmica de itens a partir de um array de dados, podem ser produtos, tarefas, posts, o que for.

Para cada item, você adiciona um botão de "Excluir".

const products = [
  { id: 'p1', name: 'Caneca de Café' },
  { id: 'p2', name: 'Mousepad Ergonômico' },
  { id: 'p3', name: 'Teclado Mecânico' }
];
 
const productListElement = document.getElementById('product-list');
 
products.forEach((product) => {
  const itemElement = document.createElement('li');
  const deleteButton = document.createElement('button');
 
  itemElement.textContent = product.name;
  deleteButton.textContent = 'Excluir';
 
  // A "mágica" acontece aqui!
  deleteButton.addEventListener('click', () => {
    console.log(`Excluindo produto com ID: ${product.id}`);
    // Lógica para remover o item da API e do DOM...
  });
 
  itemElement.appendChild(deleteButton);
  productListElement.appendChild(itemElement);
});

Versão em vídeo sobre esse conteúdo

Escopo (Scope) - As Fronteiras do seu Código

Antes de entendermos a "memória" das funções, precisamos primeiro entender onde as variáveis "vivem". É aqui que entra o conceito de Escopo.

Pense no escopo como a jurisdição ou a "bolha de visibilidade" de uma variável. Se uma variável é declarada dentro de uma determinada bolha, ela só é naturalmente acessível ali dentro e em bolhas filhas.

No Javascript, temos principalmente três tipos de escopo com os quais lidamos:

Escopo Global: Variáveis declaradas fora de qualquer função ou bloco. Elas são o "patrimônio público" do seu código, acessíveis de qualquer lugar. É uma prática recomendada evitar ao máximo poluir esse escopo.

Escopo de Função: Cada função cria sua própria "bolha". Variáveis declaradas com var, let ou const dentro de uma função pertencem a ela e não podem ser acessadas de fora.

Escopo de Bloco: Introduzido com let e const no ES6. Qualquer par de chaves (em um if, for, while ou mesmo solto no código) cria uma bolha de escopo ainda menor.

O escopo é o que nos impede de ter colisões de nomes de variáveis o tempo todo e nos ajuda a manter o código organizado. É um conceito fundamental.

Ok, simples, certo? Mas o que acontece quando estamos dentro de uma bolha e precisamos de uma variável que está na bolha externa?

Scope Chain - A Busca Pela Variável

Nenhuma função é uma ilha. Frequentemente, uma função precisa acessar variáveis de seu escopo pai. É aqui que entra a Scope Chain (ou Corrente de Escopos).

Quando o Javascript precisa encontrar o valor de uma variável, ele segue uma regra muito simples:

  1. Procure no dicionário local: Ele primeiro olha no escopo atual (a bolha mais interna). Encontrou? Ótimo, use o valor.
  2. Suba um nível: Não encontrou? Ele "sobe" para o escopo pai (a bolha que contém a bolha atual) e repete a busca por lá.
  3. Continue subindo: Esse processo continua, subindo na cadeia de escopos, até que a variável seja encontrada ou até que se chegue ao escopo global.
  4. Erro de Referência: Se a busca chegar ao escopo global e a variável ainda não for encontrada, o Javascript desiste e lança um ReferenceError.

Essa busca em cadeia, do ambiente mais interno para o mais externo, é a Scope Chain. Ela explica como funções aninhadas conseguem usar variáveis de suas "mães".

Isso nos leva diretamente à resposta do nosso exemplo inicial.

Closures - A "Mochila" de Memória do Javascript

Agora que entendemos que uma função pode acessar variáveis de seu escopo pai, a grande questão do nosso exemplo permanece: como ela faz isso se o escopo pai (a iteração do forEach) já "desapareceu"?

A resposta é que ele não desapareceu.

Quando uma função é criada, ela não apenas "sabe" qual é seu escopo pai; ela mantém um link vivo para ele. Esse link, junto com as variáveis daquele ambiente que ela precisa, é o que chamamos de Closure.

Pense nisso como uma mochila. Quando a nossa função de callback do addEventListener é criada, o Javascript dá a ela uma mochila. Dentro dessa mochila, ele coloca referências para todas as variáveis do escopo de criação que a função utiliza.

products.forEach((product) => {
  // --- Início da "bolha" da iteração ---
  // A variável 'product' existe aqui.
 
  deleteButton.addEventListener('click', () => {
    // Esta função é criada aqui DENTRO.
    // Ela "fecha" (closes over) a variável 'product' da sua iteração.
    // Ela coloca 'product' em sua "mochila".
    console.log(`Excluindo produto com ID: ${product.id}`);
  });
  // --- Fim da "bolha" da iteração ---
});

Para cada uma das três iterações do loop, um novo escopo é criado. Em cada um desses escopos, uma nova função de callback é criada. E cada uma dessas três funções de callback cria sua própria Closure, cada uma carregando em sua "mochila" uma referência para a variável product daquela iteração específica.

É por isso que o Garbage Collector (o coletor de lixo do JS) não limpa a variável product da memória. Ele vê que, embora a iteração do loop tenha terminado, existe uma função (o callback) que ainda está "viva" e segurando uma referência para aquela variável em sua "mochila".

Agora a mágica começa a parecer mais com engenharia, certo? Mas qual é a estrutura de dados que o motor do JS usa para gerenciar tudo isso?

Lexical Environment - O Coração de Tudo

Finalmente, chegamos à peça central do quebra-cabeça. Os conceitos de Escopo, Scope Chain e Closures são, na verdade, os resultados visíveis de uma estrutura interna definida na especificação do Javascript: o Lexical Environment.

Pense no Lexical Environment como o "dicionário interno" que mencionamos antes, mas de forma mais técnica. É um objeto interno que o motor do JS cria para cada escopo. Esse objeto tem duas partes principais:

  • Environment Record (Registro do Ambiente): É o armazenamento de fato, o objeto que mapeia os identificadores (nomes de variáveis e funções) para seus valores. Quando você escreve let product = ..., uma entrada para product é criada neste registro.
  • Reference to the Outer Environment (Referência ao Ambiente Externo): É simplesmente um link para o Lexical Environment do escopo pai. Para o escopo global, essa referência é null, pois ele é o topo da cadeia.

Agora, vamos amarrar tudo:

Escopo é o conceito abstrato. O Lexical Environment é a sua implementação concreta. Cada escopo tem um.

A Scope Chain é, na verdade, uma lista encadeada de Lexical Environments, conectados pela Reference to the Outer Environment. A busca por uma variável é uma travessia por essa lista.

Uma Closure é a combinação de uma função e a referência ao seu Lexical Environment de criação. A "mochila" é o Lexical Environment que a função carrega consigo. É por isso que ela "lembra": ela mantém um link para o dicionário onde suas variáveis nasceram.

No nosso exemplo do forEach, a cada iteração, um novo Lexical Environment é criado. A função de callback anônima, ao ser criada, tem sua Reference to the Outer Environment apontada para esse ambiente específico da iteração, capturando para sempre a versão correta de product.

Testando seu entendimento

Qual será o resultado no console após a execução deste código?

1for (var i = 0; i < 3; i++) {
2  setTimeout(() => {
3    console.log(i);
4  }, 10);
5}
1 / 5

Conclusão

O Lexical Environment é a estrutura de dados, a Scope Chain é o processo de busca através dessas estruturas, e a Closure é o fenômeno poderoso que observamos como resultado.

Entender isso é fundamental, pois impacta diretamente como você escreve e debuga seu código, seja para evitar "stale state" em hooks do React, para criar módulos com estado privado ou simplesmente para entender por que seu event listener funciona como o esperado.

Curtiu o artigo? Deixe seu feedback, vai ajudar bastante!

Agradeço por ter lido até aqui, grande abraço e até a próxima.

Curtiu? Compartilhe esse post:

Todos os direitos reseverdos © Junior Alves 2025