JavaScript: Escopo em JavaScript

Última atualização: 2026-10-13

O escopo determina onde uma variável pode ser acessada. Pense como um documento de identidade — seu RG só funciona dentro do seu estado, e sua habilitação não serve no exterior. Variáveis funcionam igual: quando você sai do escopo delas, ficam inacessíveis.

Declarações relacionadas:const let var for

1. Tipos de Escopo e Suas Regras

Variáveis declaradas com var, let ou const no nível mais externo têm escopo global e podem ser acessadas de qualquer lugar.

HTML
<script>
var globalVar = "Sou uma variável global";
function test() {
  console.log(globalVar); // Acessível
}
test();
</script>

Variáveis globais são práticas, mas podem facilmente poluir o namespace — conforme o projeto cresce, conflitos de nomes se tornam inevitáveis. Minimize o uso de variáveis globais.

(2) Escopo de Função

Variáveis declaradas com var seguem o escopo de função: só existem dentro da função atual e desaparecem fora dela.

HTML
<script>
function greet() {
  var message = "Olá";
  console.log(message); // Funciona
}
greet();
try {
  console.log(message); // ReferenceError!
} catch(e) {
  console.log("Falha no acesso: " + e.message);
}
</script>

Um erro clássico com o escopo de função do var: usar var em um loop for faz a variável "vazar" após o loop terminar.

(3) Escopo de Bloco

Variáveis declaradas com let e const seguem o escopo de bloco: só existem dentro do {} atual.

HTML
<script>
if (true) {
  let x = 10;
  const y = 20;
  var z = 30;
  console.log("Dentro do bloco: x=" + x + ", y=" + y + ", z=" + z);
}
console.log("Fora do bloco: z=" + z); // var não é restrita por blocos
try {
  console.log(x); // x não é acessível aqui
} catch(e) {
  console.log("x não acessível: " + e.message);
}
</script>

Por isso contadores de loop devem usar let em vez de var.

(4) Cadeia de Escopo

Escopos internos podem acessar variáveis de escopos externos — assim como você pode usar coisas de casa na escola (se tiver levado). Ao procurar uma variável, o JavaScript busca do escopo atual para fora, camada por camada, até chegar ao escopo global. Essa cadeia é chamada de cadeia de escopo.

HTML
<script>
const cidade = "São Paulo";
function externa() {
  const bairro = "Pinheiros";
  function interna() {
    const rua = "Rua dos Pinheiros";
    console.log(rua, bairro, cidade); // Tudo acessível
  }
  interna();
}
externa();
</script>

Escopos externos não podem acessar variáveis de escopos internos — assim como você não consegue enfiar a mão no bolso de um aluno de fora da sala de aula.

(5) Hoisting

Declarações com var são "elevadas" ao topo do escopo, mas as atribuições não:

HTML
<script>
console.log(a); // undefined (não é erro!)
var a = 5;
// Ordem real de execução: var a; → console.log(a); → a = 5;
</script>

let e const também sofrem hoisting, mas acessá-los antes da declaração lança um erro — essa região é chamada de Zona Morta Temporal (TDZ):

HTML
<script>
try {
  console.log(b); // ReferenceError!
} catch(e) {
  console.log("Zona morta temporal: " + e.message);
}
let b = 5;
</script>

Resumo: sempre use let e const; evite as armadilhas de hoisting do var.

(6) Closures Explicadas de Forma Intuitiva

Uma closure = uma função + o ambiente de variáveis onde ela nasceu. É como alguém que saiu da cidade natal, mas continua lembrando como era — mesmo que a cidade tenha mudado depois, a memória permanece a mesma.

HTML
<script>
function criarContador() {
  let contagem = 0;        // Esta variável fica "trancada" dentro da closure
  return function() {
    contagem++;
    return contagem;
  };
}

const contador = criarContador();
console.log(contador()); // 1
console.log(contador()); // 2
console.log(contador()); // 3
// A variável contagem não foi destruída porque a função retornada ainda "lembra" dela
</script>

criarContador já terminou de executar — logicamente, contagem deveria ser destruída. Mas a função retornada segura contagem com força, então ela sobrevive. Isso é uma closure.

(7) Casos Práticos de Uso de Closures


▶ Exemplo: var vs let em Loops

▶ Experimente

▶ Exemplo: Demonstração da Cadeia de Escopo

▶ Experimente

▶ Exemplo: Contador com Closure e Variáveis Privadas

▶ Experimente

▶ Exemplo: Comparação de Hoisting

▶ Experimente

Declarações relacionadas:const let var for

❓ Perguntas Frequentes

P Por que usar var em um loop for faz todos os callbacks mostrarem o mesmo valor?
R Porque var tem escopo de função — depois que o loop termina, existe apenas um i, e todos os callbacks compartilham ele (que já vale o valor final do loop). Com let, cada iteração recebe sua própria cópia independente de i.
P Causam vazamento de memória as closures?
R Closures em si não são vazamentos — elas mantêm referências às variáveis intencionalmente. Um vazamento real acontece quando você não precisa mais de uma closure, mas ela ainda é mantida por outra cadeia de referências, impedindo a coleta de lixo. A solução: atribuir null à referência.
P Devo usar let ou const?
R Use const por padrão; só use let quando precisar reatribuir. Esse hábito evita que você modifique acidentalmente variáveis que não deveriam mudar.

📖 Resumo


📝 Exercícios

  1. Escreva uma função criarSaudacao(saudacao) que retorne uma função que, ao receber um nome, retorne saudacao + ", " + nome. Crie duas funções de saudação com saudações diferentes e verifique que não interferem uma na outra.
  2. Escreva uma função criarCarteira(saldoInicial) que retorne três métodos: depositar, sacar e obterSaldo. O saldo não deve ser acessível diretamente de fora (variável privada) — só pode ser manipulado por esses métodos.
  3. Explique a saída do código abaixo e o motivo:
HTML
<script>
for (var i = 0; i < 3; i++) {
  setTimeout(function() { console.log(i); }, 100);
}
</script>

Depois modifique para exibir 0, 1, 2.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%