Back

Um Guia Rápido sobre Escopo Global em JavaScript

Um Guia Rápido sobre Escopo Global em JavaScript

Quando você declara uma variável no nível superior de um arquivo JavaScript, onde ela realmente fica armazenada? A resposta depende de você estar escrevendo um script clássico ou um módulo ES—e errar isso leva a bugs sutis que são frustrantes de depurar.

Este guia explica como o escopo global do JavaScript funciona no desenvolvimento moderno, por que globalThis é a forma confiável de referenciar o objeto global, e como var, let e const se comportam de maneira diferente no nível superior.

Pontos-Chave

  • O comportamento do escopo global difere entre scripts clássicos e módulos ES—apenas var em scripts clássicos cria propriedades no objeto global.
  • let e const criam vínculos globais mas não se anexam ao objeto global.
  • Use globalThis para compatibilidade entre ambientes quando precisar acessar o objeto global.
  • Prefira módulos ES para isolamento automático de escopo e para evitar poluição não intencional do namespace.

O Que É Escopo Global em JavaScript?

Escopo global refere-se ao escopo mais externo no seu ambiente JavaScript. Variáveis no escopo global são acessíveis de qualquer lugar no seu código—dentro de funções, blocos ou módulos aninhados.

Mas aqui está a distinção crítica que a maioria dos tutoriais perde: o escopo de nível superior em JavaScript se comporta de forma diferente dependendo de como seu script é carregado.

Scripts Clássicos vs Módulos ES

Em um script clássico (carregado sem type="module"), variáveis de nível superior declaradas com var tornam-se propriedades do objeto global:

// classic script
var config = { debug: true }
console.log(globalThis.config) // { debug: true }

Com módulos ES, isso muda completamente. Módulos e escopo global funcionam de forma diferente por design. Vínculos de nível superior em um módulo permanecem dentro do escopo daquele módulo—eles não se anexam ao objeto global:

// module script (type="module")
var config = { debug: true }
console.log(globalThis.config) // undefined

Esse isolamento é intencional. Módulos fornecem encapsulamento, prevenindo poluição acidental do namespace entre arquivos. Veja o guia da MDN sobre módulos JavaScript para uma referência mais aprofundada.

Como var, let e const Diferem no Nível Superior

Mesmo em scripts clássicos, let e const se comportam de forma diferente de var:

// classic script
var a = 1
let b = 2
const c = 3

console.log(globalThis.a) // 1
console.log(globalThis.b) // undefined
console.log(globalThis.c) // undefined

Apenas var cria uma propriedade no objeto global. Tanto let quanto const criam vínculos no escopo global que são acessíveis em todo o seu código, mas não se tornam propriedades do objeto global.

Essa distinção importa quando scripts de terceiros esperam encontrar suas variáveis no objeto global, ou quando você está depurando e verificando-o diretamente.

Por Que globalThis É o Padrão Moderno

Diferentes ambientes JavaScript historicamente usavam nomes diferentes para o objeto global:

  • Navegadores usam window
  • Node.js usa global
  • Web Workers usam self

Escrever código entre ambientes significava verificar qual global existia. O padrão globalThis resolve isso fornecendo uma referência universal:

// Works everywhere
globalThis.sharedValue = 'accessible across environments'

Usar globalThis garante que seu código execute corretamente seja em um navegador, Node.js, Deno ou um Web Worker. É a abordagem correta e agnóstica de plataforma.

Sombreamento de Variáveis no Escopo Global

Um equívoco comum: você não pode redeclarar uma variável let ou const que já existe no escopo global. No entanto, você pode sombrear vínculos var introduzidos globalmente com declarações léxicas—incluindo vínculos var introduzidos dinamicamente (por exemplo, via eval) em engines modernas:

var x = 1
{
  let x = 2 // shadows the global var
  console.log(x) // 2
}
console.log(x) // 1

O let x interno cria uma variável separada que temporariamente oculta o var x externo dentro daquele bloco. São vínculos distintos—modificar um não afeta o outro.

Recursos Exclusivos de Módulos: Top-Level Await

Uma diferença prática com escopo de nível superior que desenvolvedores JavaScript devem conhecer: await no nível superior só funciona em módulos:

// Only valid in modules
const data = await fetch('/api/config').then(r => r.json())

Scripts clássicos não suportam essa sintaxe. Se você precisa de await no nível superior, deve usar type="module" na sua tag de script.

Melhores Práticas para Escopo Global

  1. Prefira módulos — Eles fornecem isolamento automático de escopo e imports/exports explícitos
  2. Use globalThis — Quando você genuinamente precisar do objeto global, isso funciona em todos os lugares
  3. Evite var no nível superior — Use let ou const para prevenir poluição não intencional do objeto global
  4. Seja explícito sobre globais — Se algo deve ser global, anexe-o ao globalThis intencionalmente ao invés de depender de comportamento implícito

Conclusão

Escopo global em JavaScript não é tão simples quanto “variáveis acessíveis em todos os lugares”. Scripts clássicos e módulos ES lidam com vínculos de nível superior de forma diferente, e apenas var em scripts clássicos cria propriedades do objeto global. Use globalThis para compatibilidade entre ambientes, e prefira módulos por seu encapsulamento integrado. Entender essas distinções ajuda você a escrever código previsível que funciona em diferentes ambientes JavaScript.

Perguntas Frequentes

Sim, mas apenas se ambos os scripts forem scripts clássicos e compartilharem o mesmo escopo global. As variáveis são acessíveis pelo nome entre scripts, mas não são propriedades do objeto global. Se qualquer script for um módulo ES, as variáveis permanecem privadas àquele módulo a menos que sejam explicitamente exportadas.

Use o objeto global quando precisar compartilhar dados com scripts que você não controla, como analytics de terceiros ou código legado que espera globais. Use também para polyfills que devem estar universalmente disponíveis. Para código que você controla, prefira exports de módulo para melhor encapsulamento e rastreamento explícito de dependências.

globalThis é suportado em todos os ambientes JavaScript modernos. Se você precisa dar suporte a plataformas legadas como Internet Explorer, use um polyfill ou dependa do seu bundler/transpilador para fornecer um.

Esta é uma decisão de design histórica. var fazia parte do JavaScript desde o início e foi projetado para criar propriedades do objeto global para interoperabilidade. let e const foram introduzidos no ES6 com regras de escopo mais estritas para evitar as armadilhas da poluição global implícita enquanto ainda permitem acessibilidade global.