JavaScript globalThis e o Objeto Global
Aprenda o objeto global do JavaScript: globalThis vs window vs global, o que contém, por que var e funções de nível superior vazam para ele e como evitar poluir o namespace global.
Todo programa JavaScript é executado dentro de um objeto de nível superior que existe antes de o seu código começar: o objeto global. Ele contém os recursos nativos da linguagem (Array, Math, JSON, setTimeout, etc.) e é o destino implícito de tudo o que você declara no topo de um script clássico. Esta página explica o que é o objeto global, como acessá-lo de forma portável com globalThis, o que realmente existe nele, por que algumas declarações de nível superior "vazam" para ele enquanto outras não, e como manter seus próprios globais sob controle.
O que é o objeto global
O objeto global é a raiz da cadeia de escopos. Quando você referencia um nome que não é encontrado em nenhuma função ou escopo de bloco envolvente, o motor finalmente o procura como uma propriedade do objeto global. É por isso que Math.max ou JSON.parse funcionam em qualquer lugar — eles são propriedades do objeto global que o ambiente de execução configura para você.
Cada ambiente de execução expõe esse objeto com um nome diferente, o que historicamente tornava o código entre ambientes complicado:
- Navegadores chamam de
window(e também expõemselfeframes). - Web Workers chamam de
self(não háwindowem um worker). - Node.js chama de
global.
globalThis: o global portável
Como o nome varia por ambiente, o ES2020 adicionou globalThis — uma única referência padrão que aponta para o objeto global em todos os lugares: navegadores, workers, Node.js, Deno e mais. Use-o sempre que precisar do objeto global real em código que deve ser executado em mais de um lugar.
console.log(typeof globalThis); // "object" in every environment
// Each of these is true only in its own environment:
// globalThis === window -> true in a browser tab
// globalThis === self -> true in a browser or a Web Worker
// globalThis === global -> true in Node.jsTentar usar o nome errado lança um ReferenceError, que é exatamente o problema que globalThis resolve:
Para uma visão mais ampla do que um ambiente hospedeiro adiciona sobre a linguagem, veja o ambiente do navegador e especificações.
O que existe no objeto global
O objeto global carrega dois tipos de coisas:
- Recursos nativos da linguagem, definidos pela especificação ECMAScript e presentes em todos os lugares:
Object,Array,Function,String,Number,Boolean,Symbol,BigInt,Math,JSON,Date,RegExp,Promise,Map,Set, os construtores de erros e funções globais comoparseInt,isNaNeeval. - APIs do host (ambiente), adicionadas pelo ambiente de execução:
document,fetch,localStorage,setTimeoutealertno navegador;process,Buffererequireno Node.js.
// Built-ins are reachable through the global object:
console.log(globalThis.Math.max(2, 7, 4)); // 7
console.log(globalThis.JSON.stringify({ ok: true })); // {"ok":true}Por que var e funções de nível superior vazam para o objeto global
Em um script de navegador clássico (não-módulo), um var declarado no nível superior e uma declaração de função de nível superior se tornam propriedades de window. Este é um comportamento legado incorporado na linguagem por compatibilidade retroativa:
// In a classic browser script (not a module):
var greeting = 'hi';
function greet() { return greeting; }
console.log(window.greeting); // "hi"
console.log(typeof window.greet); // "function"Declarações com escopo de bloco se comportam de forma diferente. let, const e class no nível superior criam ligações globais, mas não se anexam ao objeto global:
let count = 1;
const name = 'app';
console.log(window.count); // undefined
console.log(window.name); // "" — note: window.name is a pre-existing browser property, not your variableDuas ressalvas importantes:
- Módulos ES não vazam de forma alguma. Declarações de
varefunctionde nível superior dentro de um<script type="module">(ou qualquer arquivo comimport/export) têm escopo de módulo, então nada — nem mesmovar— se anexa ao objeto global. - Arquivos Node.js também são módulos. Um
varde nível superior em um arquivo.jsdo Node tem escopo naquele módulo, portanto não se anexa aglobalcomo um script de navegador clássico faria.
Essa diferença é uma das razões práticas pelas quais o código moderno prefere let/const e módulos. Para a história completa de hoisting e escopo por trás do var, leia o antigo "var" e escopo de variável e closure.
Evitando poluição global
Globais são estado compartilhado e mutável: qualquer script pode sobrescrevê-los, e colisões de nomes causam bugs difíceis de rastrear. Alguns hábitos mantêm o namespace limpo:
- Prefira
let/conste módulos. Eles mantêm as declarações completamente fora do objeto global. - Use um único namespace quando você realmente precisar de um global, para que você adicione uma propriedade em vez de muitas.
- Ative o modo estrito.
"use strict"faz com que uma atribuição não declarada comox = 5lance um erro em vez de criar silenciosamente um global.
Módulos ES mantêm o namespace global limpo
Módulos ES dividem o código em arquivos reutilizáveis cujas declarações de nível superior permanecem privadas para cada arquivo, a menos que sejam explicitamente exportadas. Esta é a alternativa moderna a anexar coisas ao objeto global:
// file: math.js
export const add = (a, b) => a + b;
// file: app.js
import { add } from './math.js';
console.log(add(2, 3)); // 5
// `add` is imported, not read from a global — nothing leaks onto window/global.Conclusão
O objeto global é o escopo raiz do ambiente de execução: ele hospeda os recursos nativos da linguagem e as APIs do host e, em scripts clássicos, também coleta declarações de var e function de nível superior. Use globalThis para acessá-lo de forma portável, apoie-se em let/const e módulos para evitar poluí-lo, e ative o modo estrito para detectar globais acidentais logo cedo.