W3docs

JavaScript globalThis e l'oggetto globale

Scopri l'oggetto globale JavaScript: globalThis vs window vs global, cosa contiene, perché var e le funzioni di primo livello vi si aggiungono e come evitare di inquinare lo spazio dei nomi globale.

Ogni programma JavaScript viene eseguito all'interno di un oggetto di primo livello che esiste prima dell'avvio del codice: l'oggetto globale. Esso contiene i built-in del linguaggio (Array, Math, JSON, setTimeout e così via) e rappresenta la sede implicita di tutto ciò che si dichiara al livello più alto di uno script classico. Questa pagina spiega cos'è l'oggetto globale, come raggiungerlo in modo portabile con globalThis, cosa vi risiede effettivamente, perché alcune dichiarazioni di primo livello vi "trapelano" mentre altre no, e come tenere sotto controllo le proprie variabili globali.

Cos'è l'oggetto globale

L'oggetto globale è la radice della catena degli scope. Quando si fa riferimento a un nome che non viene trovato in nessuno scope di funzione o blocco circostante, il motore lo cerca infine come proprietà dell'oggetto globale. Ecco perché Math.max o JSON.parse funzionano ovunque — sono proprietà dell'oggetto globale che il runtime predispone automaticamente.

Ogni runtime espone quell'oggetto con un nome diverso, il che ha storicamente reso complicato scrivere codice cross-environment:

  • I browser lo chiamano window (e rendono disponibili anche self e frames).
  • I Web Worker lo chiamano self (non esiste window in un worker).
  • Node.js lo chiama global.

globalThis: il globale portabile

Poiché il nome varia per ambiente, ES2020 ha introdotto globalThis — un unico riferimento standard che punta all'oggetto globale ovunque: browser, worker, Node.js, Deno e altro ancora. Ricorriti ogni volta che hai bisogno del vero oggetto globale in codice che deve essere eseguito in più ambienti.

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.js

Tentare di usare il nome sbagliato genera un ReferenceError, che è esattamente il problema che globalThis risolve:

javascript— editable

Per un quadro più ampio di ciò che un ambiente host aggiunge al linguaggio, consulta l'ambiente browser e le specifiche.

Cosa si trova sull'oggetto globale

L'oggetto globale ospita due tipi di elementi:

  1. Built-in del linguaggio, definiti dalla specifica ECMAScript e presenti ovunque: Object, Array, Function, String, Number, Boolean, Symbol, BigInt, Math, JSON, Date, RegExp, Promise, Map, Set, i costruttori degli errori e le funzioni globali come parseInt, isNaN e eval.
  2. API host (dell'ambiente), aggiunte dal runtime: document, fetch, localStorage, setTimeout e alert nel browser; process, Buffer e require in 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}

Perché var e le funzioni di primo livello vi trapelano

In uno script browser classico (non modulo), un var dichiarato al livello più alto e una dichiarazione function di primo livello diventano entrambi proprietà di window. Questo è un comportamento legacy incorporato nel linguaggio per compatibilità con le versioni precedenti:

// 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"

Le dichiarazioni con scope di blocco si comportano diversamente. let, const e class al livello più alto creano binding globali ma non si collegano all'oggetto globale:

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 variable

Due avvertenze importanti:

  • I moduli ES non trapelano affatto. Le dichiarazioni var e function di primo livello all'interno di un <script type="module"> (o qualsiasi file con import/export) hanno scope di modulo, quindi nulla — nemmeno var — si aggancia all'oggetto globale.
  • Anche i file Node.js sono moduli. Un var di primo livello in un file Node .js ha scope nel modulo, quindi non si aggancia a global come farebbe uno script browser classico.

Questa differenza è uno dei motivi pratici per cui il codice moderno preferisce let/const e i moduli. Per la storia completa di hoisting e scoping relativa a var, leggi il vecchio "var" e scope delle variabili e closure.

Evitare l'inquinamento globale

Le variabili globali sono stato condiviso e mutabile: qualsiasi script può sovrascriverle, e le collisioni di nomi causano bug difficili da tracciare. Alcune abitudini mantengono il namespace pulito:

  • Preferire let/const e i moduli. Tengono le dichiarazioni completamente fuori dall'oggetto globale.
  • Usare un unico namespace quando si ha realmente bisogno di un globale, in modo da aggiungere una sola proprietà anziché molte.
  • Attivare la strict mode. "use strict" fa sì che un'assegnazione non dichiarata come x = 5 generi un errore anziché creare silenziosamente un globale.
javascript— editable

I moduli ES mantengono pulito il namespace globale

I moduli ES suddividono il codice in file riutilizzabili le cui dichiarazioni di primo livello rimangono private a ciascun file a meno che non vengano esportate esplicitamente. Questa è l'alternativa moderna all'aggiungere cose all'oggetto globale:

// 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.

Conclusione

L'oggetto globale è lo scope radice del runtime: ospita i built-in del linguaggio e le API host, e negli script classici raccoglie anche le dichiarazioni var e function di primo livello. Usa globalThis per raggiungerlo in modo portabile, affidati a let/const e ai moduli per evitare di inquinarlo, e abilita la strict mode per intercettare i globali accidentali fin dall'inizio.

Esercizio

Pratica
Quali delle seguenti sono le migliori pratiche quando si usa l'oggetto globale in JavaScript?
Quali delle seguenti sono le migliori pratiche quando si usa l'oggetto globale in JavaScript?
Was this page helpful?