Diego Betto's Blog
Photo by MJ Duford on Unsplash

Diego Betto · 10 settembre 2026 · 4 min di lettura

"Cannot access before initialization": la Temporal Dead Zone spiegata

Perché let e const lanciano ReferenceError invece di restituire undefined come var, cos'è davvero la Temporal Dead Zone, e i pattern che la scatenano per errore.

Condividi:XLinkedInFacebookWhatsApp

Fai riferimento a una variabile chiaramente dichiarata più sotto nello stesso scope, aspettandoti la solita elasticità di JavaScript, e invece ottieni:

⛔ Errore

ReferenceError: Cannot access ‘config’ before initialization

Se vieni da var, o da un linguaggio senza questa regola esatta, è sorprendente — var ti avrebbe semplicemente dato undefined invece di lanciare un errore. La differenza è la Temporal Dead Zone, e una volta capita, questo errore smette di essere confuso.

Hoisting di var vs hoisting di let/const

Tutti e tre — var, let e const — sono soggetti a hoisting: il motore conosce l’esistenza della variabile fin dall’inizio del suo scope. La differenza è cosa succede tra l’inizio dello scope e la riga di dichiarazione effettiva.

console.log(x); // undefined — var è hoisted E inizializzata a undefined
var x = 5;
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 5;

var viene hoisted e inizializzata immediatamente a undefined. let e const vengono hoisted ma restano non inizializzate finché l’esecuzione non raggiunge davvero la loro dichiarazione. Il tratto di codice tra l’inizio dello scope e quella dichiarazione — dove la variabile esiste ma toccarla lancia un errore — è la Temporal Dead Zone (TDZ).

Perché esiste la TDZ

Non è una restrizione arbitraria — intercetta una vera classe di bug. Con var, leggere una variabile prima della sua dichiarazione dà silenziosamente undefined, il che spesso maschera un errore logico (volevi usarla dopo che era stata impostata, ma un refuso o un refactoring ha spostato la lettura prima). La TDZ trasforma quell’undefined silenzioso in un errore rumoroso e immediato esattamente nel punto in cui hai provato a usare il valore non ancora inizializzato.

Dove compare nel codice reale

Oscurare accidentalmente una variabile esterna

let value = "esterno";

function example() {
  console.log(value); // lancia — non "esterno"!
  let value = "interno";
}

example();

È facile presumere che console.log(value) legga il value esterno, dato che è ciò che succederebbe con var. Non è così — let value dentro example viene hoisted in cima alla funzione, oscurando la variabile esterna per tutto il corpo della funzione, inclusa la riga prima della propria dichiarazione. Quella riga è nella TDZ per il value interno, quindi lancia un errore invece di leggere silenziosamente quello esterno.

Un parametro di default che fa riferimento a se stesso

function greet(name = greeting, greeting = "Ciao") {
  return `${greeting}, ${name}`;
}

greet(); // ReferenceError: Cannot access 'greeting' before initialization

I parametri di default vengono valutati da sinistra a destra, e ognuno è nella TDZ finché il proprio default non è stato assegnato — il default di name prova a leggere greeting prima che greeting sia stato inizializzato. Riordinare i parametri risolve il problema.

Anche le dichiarazioni class sono nella TDZ

new Vehicle(); // ReferenceError — le classi sono hoisted ma restano nella TDZ
class Vehicle {}

Questo sorprende chi viene da altri linguaggi orientati agli oggetti dove le dichiarazioni di classe sono tipicamente disponibili in tutto il file. In JavaScript, class si comporta come let/const per questo scopo, non come una dichiarazione di funzione (che è completamente hoisted e chiamabile prima della sua posizione testuale).

var vs let/const: confronto diretto

var let / const
Hoisted
Inizializzata al momento dell’hoist Sì, a undefined No — resta nella TDZ
Accesso prima della dichiarazione Restituisce undefined Lancia ReferenceError
Scope Di funzione Di blocco

FAQ

❓ La TDZ è un bug di JavaScript o un bug del mio codice?

Né l’uno né l’altro, esattamente — è il linguaggio che fallisce deliberatamente in modo rumoroso invece di restituire silenziosamente undefined. Se ci incappi, quasi sempre c’è un vero problema di ordinamento nel tuo codice che vale la pena correggere (una variabile oscurata, un parametro di default nell’ordine sbagliato), non qualcosa da aggirare.

❓ La TDZ vale anche per i parametri di funzione?

Sì — i parametri sono essenzialmente scope-let all’interno della funzione, il che è esattamente il motivo per cui l’esempio del parametro di default auto-referenziante sopra lancia un errore.

❓ typeof evita di scatenare la TDZ, come fa per le variabili non dichiarate?

No, ed è un’eccezione sottile ma importante: typeof unaVariabileNonDichiarata normalmente restituisce in sicurezza "undefined" per una variabile mai dichiarata affatto, ma typeof su una variabile let/const ancora nella sua TDZ lancia lo stesso ReferenceError — la TDZ rende insicuro anche typeof per quella specifica variabile.

Conclusione

La Temporal Dead Zone è JavaScript che converte una categoria di bug silenzioso — leggere una var prima della sua assegnazione prevista e ottenere undefined senza nessun avviso — in un ReferenceError rumoroso e immediato per let, const e class. I tre pattern sopra (oscuramento accidentale, parametro di default auto-referenziante, e riferimento anticipato a una classe) coprono quasi ogni caso reale; una volta riconosciuta la forma, la correzione è di solito solo riordinare il codice.

Riferimenti

Condividi:XLinkedInFacebookWhatsApp
Diego Betto

Scritto da

Diego Betto

Co-Fondatore & CTO presso PAPION. Senior full-stack engineer specializzato in React, TypeScript, Node.js e sicurezza applicativa.