Escopo de variáveis
Entenda onde cada variável pode ser acessada, como nomes são resolvidos entre ambientes e por que limitar o escopo reduz dependências e erros.

Escopo define onde um nome pode ser usado
O escopo de uma variável é a região do programa na qual seu nome pode ser encontrado e associado à declaração correta. Fora dessa região, usar o mesmo nome pode causar erro, encontrar outra declaração ou ter um significado diferente, conforme a linguagem.
Considere este exemplo em JavaScript:
const moeda = "BRL";
function calcularTotal(subtotal) {
const taxa = 0.10;
const total = subtotal + subtotal * taxa;
return total;
}
const resultado = calcularTotal(200);
console.log(resultado); // 220
Há três papéis diferentes:
moedaestá declarada fora da função e pertence ao ambiente mais externo desse exemplo;subtotalé um parâmetro local criado para cada chamada;taxaetotalsão nomes locais da função.
O código externo pode usar resultado, mas não pode acessar diretamente taxa ou total. Esses nomes só existem para o corpo de calcularTotal. A função, por sua vez, pode consultar nomes de ambientes externos, como moeda, caso não encontre uma declaração local com o mesmo nome.
Essa é uma diferença importante em relação a variáveis e constantes: declarar e atualizar explicam o estado armazenado; escopo explica onde o nome desse estado é visível.
Procure do ambiente mais próximo para fora
Quando encontra um identificador, uma linguagem com escopo léxico normalmente procura primeiro no ambiente atual. Se o nome não estiver ali, examina ambientes que envolvem aquele trecho, do mais próximo para o mais distante, seguindo as regras da linguagem.
const moeda = "BRL";
function formatarPreco(valor) {
const separador = ",";
if (valor >= 1000) {
const prefixo = "A partir de";
return `${prefixo} ${moeda} ${valor}${separador}00`;
}
return `${moeda} ${valor}${separador}00`;
}
Dentro do bloco do if, a resolução encontra:
prefixono próprio bloco;valoreseparadorno escopo da função;moedano escopo externo.
Fora do bloco, prefixo não está disponível. Fora da função, valor e separador também não estão. O acesso se propaga dos ambientes internos para os externos; uma região externa não ganha acesso automático aos nomes exclusivos de uma região interna.
Esse modelo permite diagnosticar uma referência sem adivinhar: marque o ponto de uso, liste os ambientes que o envolvem e procure a primeira declaração compatível.
Parâmetros e variáveis da função são locais à chamada
Cada execução de uma função cria seu próprio conjunto de parâmetros e variáveis locais. Duas chamadas podem usar os mesmos nomes sem compartilhar automaticamente os mesmos valores:
function aplicarDesconto(subtotal, percentual) {
const desconto = subtotal * (percentual / 100);
return subtotal - desconto;
}
const totalA = aplicarDesconto(200, 10); // desconto local: 20
const totalB = aplicarDesconto(80, 5); // desconto local: 4
O desconto da primeira chamada não é reutilizado pela segunda. Cada chamada calcula um valor local independente. Depois que a função termina, seu nome local deixa de estar acessível pelo código chamador; somente o valor entregue por retorno atravessa explicitamente essa fronteira.
Esse isolamento ajuda a reutilização. O chamador informa as dependências pelos argumentos, a função trabalha com estado local e devolve um resultado. Não é necessário criar nomes globais diferentes para cada compra.
Blocos podem criar fronteiras menores
Um bloco é uma região delimitada por chaves, indentação ou palavras de início e fim. Entretanto, bloco visual e escopo de variável não são universais.
Em JavaScript, declarações com let e const pertencem ao bloco que as contém:
if (pedidoAprovado) {
const mensagem = "Pedido aprovado";
console.log(mensagem); // disponível
}
console.log(mensagem); // ReferenceError
Em C#, uma variável local declarada em um bloco também fica limitada a esse bloco. Em Python, por outro lado, blocos de if, for e while não criam um novo escopo local de função: uma atribuição feita neles pertence ao bloco de código da função. Funções, módulos e classes participam da resolução de nomes segundo regras próprias.
| Construção | JavaScript com let/const | C# | Python |
|---|---|---|---|
| função | cria escopo local | cria espaço local | cria escopo local |
bloco if | cria escopo de bloco | limita variáveis locais declaradas nele | não cria novo escopo local de função |
| laço | let/const seguem o bloco | variável local segue a construção | alvo do laço pertence ao escopo da função |
A tabela serve como orientação, não como substituto da documentação. Ao trocar de linguagem, confirme quais construções realmente introduzem uma fronteira de escopo.
Nomes iguais podem provocar sombreamento
Quando um ambiente interno declara um nome já existente no ambiente externo, a declaração mais próxima pode sombrear a outra. Em JavaScript:
const saldo = 100;
{
const saldo = 50;
console.log(saldo); // 50
}
console.log(saldo); // 100
O bloco não alterou o primeiro saldo. Ele criou outra ligação com o mesmo nome. Dentro do bloco, a busca encontra saldo = 50 primeiro; depois do bloco, a declaração externa volta a ser a visível.
As permissões variam. JavaScript aceita esse exemplo com const em blocos aninhados. Python decide os nomes locais de uma função ao analisar as operações de ligação presentes no bloco inteiro, o que pode gerar UnboundLocalError quando um nome é lido antes da atribuição local. C# restringe determinadas redeclarações de variáveis locais em espaços aninhados.
Mesmo quando permitido, sombreamento pode confundir. Nomes como total, status e resultado repetidos em muitos níveis tornam difícil saber qual dado uma linha utiliza. Mantenha o mesmo nome quando a distinção estiver evidente e curta; renomeie quando os conceitos forem diferentes, como subtotal e totalComFrete.
Escopo e tempo de vida respondem a perguntas diferentes
Escopo responde: em qual trecho posso escrever este nome? Tempo de vida responde: por quanto tempo o valor ou objeto permanece disponível na execução?
Na maioria dos exemplos simples, uma variável local só pode ser referenciada dentro da função e deixa de ser necessária quando a chamada termina. Mas as duas ideias não são idênticas. Uma função interna pode capturar uma ligação do ambiente em que foi criada:
function criarContador() {
let valor = 0;
return function incrementar() {
valor += 1;
return valor;
};
}
const proximo = criarContador();
console.log(proximo()); // 1
console.log(proximo()); // 2
O código externo continua sem poder usar o nome valor diretamente. Ainda assim, a função retornada conserva acesso à ligação por meio de um closure. O exemplo demonstra por que “saiu do bloco” não significa necessariamente “o objeto já foi destruído”. O funcionamento aprofundado de closures fica para estudos posteriores; aqui, guarde apenas a separação entre visibilidade do nome e duração do estado.
Variáveis globais criam dependências que não aparecem na chamada
Um nome global pode ser conveniente para uma constante compartilhada ou uma configuração controlada. O problema aparece quando funções leem e alteram estado global mutável sem deixar essa dependência explícita:
let taxa = 0.10;
function calcularTotal(subtotal) {
return subtotal + subtotal * taxa;
}
A chamada calcularTotal(200) parece depender apenas de 200, mas seu resultado também depende do valor atual de taxa. Outro trecho pode mudar a variável antes da chamada, fazendo o mesmo argumento produzir outra resposta.
Uma interface explícita facilita leitura e teste:
function calcularTotal(subtotal, taxa) {
return subtotal + subtotal * taxa;
}
const total = calcularTotal(200, 0.10); // 220
Isso não transforma todo nome externo em erro. Constantes imutáveis de módulo, serviços deliberadamente compartilhados e configurações possuem usos legítimos. A pergunta prática é: “se este valor mudar, quais partes do programa mudam de comportamento?”. Quanto mais difícil for responder, maior é o custo do alcance amplo.
Prefira o menor escopo que atende ao uso real
Uma variável deve ser declarada perto do primeiro uso e permanecer visível apenas pelo tempo necessário para cumprir sua responsabilidade. Um alcance menor:
- reduz a quantidade de lugares capazes de ler ou alterar o estado;
- evita colisões entre nomes genéricos;
- deixa dependências mais fáceis de identificar;
- simplifica testes e mudanças;
- reduz o estado que o leitor precisa manter mentalmente.
Não mova toda declaração para o bloco mais interno sem avaliar o fluxo. Se um resultado calculado em uma condição precisa ser usado depois, talvez a variável pertença ao escopo externo comum, ou talvez cada caminho possa retornar seu resultado diretamente. A escolha deve refletir onde o dado é realmente necessário.
Ao revisar uma variável, use este roteiro:
- marque onde ela é declarada;
- liste todos os pontos de leitura e alteração;
- identifique a menor região que contém esses usos;
- verifique se existe outro nome igual em ambiente aninhado;
- transforme dependências externas mutáveis em parâmetros quando isso esclarecer o contrato;
- confirme as regras da linguagem para função, bloco, módulo e laço.
Faça um teste de visibilidade
Analise o exemplo:
const percentual = 10;
function calcular(preco) {
const subtotal = preco * 2;
if (subtotal >= 100) {
const percentual = 20;
const desconto = subtotal * (percentual / 100);
return subtotal - desconto;
}
return subtotal;
}
Sem executar o código, responda:
- qual
percentualé encontrado dentro doif? - o
percentualglobal foi alterado? descontopode ser lido depois do bloco?subtotalpode ser usado em ambos os retornos?- o chamador consegue acessar
subtotaldiretamente? - quais resultados surgem para
calcular(60)ecalcular(30)?
As respostas são: o percentual local 20; o global continua 10; desconto fica restrito ao bloco; subtotal pertence à função e está disponível nos dois caminhos; o chamador recebe apenas o retorno; e os resultados são 96 e 60.
Depois, renomeie o valor interno para percentualPromocional. O comportamento não muda, mas a intenção fica mais fácil de seguir. Esse contraste mostra que um programa pode estar correto para a linguagem e ainda ser desnecessariamente difícil para pessoas.
O que você deve guardar
Escopo é a região em que um nome está visível. Para resolver uma referência, comece no ponto de uso e procure nos ambientes permitidos, do mais próximo para fora. Parâmetros e variáveis locais isolam cada chamada; blocos podem criar fronteiras adicionais, dependendo da linguagem.
Sombreamento cria declarações distintas com o mesmo nome, escopo não é sinônimo de tempo de vida e estado global mutável pode esconder dependências. Prefira o menor alcance que cubra os usos reais e torne entradas e saídas explícitas. Com funções, parâmetros, retornos e escopo organizados, veja como cada chamada mantém seus próprios valores em introdução à recursividade.
Referências
- MDN Web Docs — Scope. Acesso em 11 set. 2026.
- MDN Web Docs — Grammar and types: variable scope. Acesso em 11 set. 2026.
- MDN Web Docs — Block statement. Acesso em 11 set. 2026.
- MDN Web Docs — Closures. Acesso em 11 set. 2026.
- Python 3 Documentation — Execution model: resolution of names. Acesso em 11 set. 2026.
- Microsoft Learn — C# statements: blocks define variable scope. Acesso em 11 set. 2026.
- Microsoft Learn — C# language specification: scopes. Acesso em 11 set. 2026.