Var, Let e Const in JavaScript: La Guida Definitiva a Scope e Hoisting (2026)

Ancora confuso su quando usare var, let o const? Smetti di tirare a indovinare. Scopri la guida definitiva 2026 su Scope, Hoisting e Temporal Dead Zone per scrivere JavaScript moderno, sicuro e privo di bug.

Aggiornato: Febbraio 2026

Ancora confuso su quando usare var, let o const? Smetti di tirare a indovinare. Scopri la guida definitiva 2026 su Scope, Hoisting e Temporal Dead Zone per scrivere JavaScript moderno, sicuro e privo di bug.

Se hai iniziato a programmare con JavaScript prima del 2015, il tuo vocabolario per le variabili si limitava a una sola parola: var. Tuttavia, padroneggiare la triade var, let e const è oggi la competenza fondamentale per ogni sviluppatore moderno.

JavaScript è un linguaggio di programmazione dinamico e flessibile, e proprio questa flessibilità ha storicamente portato a bug difficili da individuare. L’introduzione di ES6 (ECMAScript 2015) non ha portato solo “nuova sintassi”, ma ha risolto problemi architetturali storici del linguaggio. Comprendere le differenze non è solo una questione di stile; è la base per scrivere codice pulito (Clean Code), sicuro e performante.

In questa guida completa, analizzeremo non solo il come, ma il perché tecnico dietro Scope, Hoisting e la gestione della memoria.


Tabella Riassuntiva Rapida: Le Differenze

Prima di scendere nei dettagli tecnici, ecco la mappa mentale fondamentale:

Caratteristicavar (Legacy)let (Moderno)const (Moderno)
ScopeFunction Scope 🏠Block Scope 📦Block Scope 📦
Riassegnabile?✅ Sì✅ Sì❌ No
HoistingSì (inizializzato undefined)Sì (in TDZ 💀)Sì (in TDZ 💀)
Global PollutionSì (va su window)NoNo

1. La Battaglia dello Scope: Dove vive la tua variabile?

Lo scope definisce l’area del codice in cui una variabile è “visibile”. Questa è la distinzione più critica e il motivo principale per cui var è stata quasi del tutto abbandonata.

1.1 var: Scope di Funzione (Il vecchio approccio)

Le variabili dichiarate con var ignorano i blocchi di codice come if o for. Esse “vedono” solo i confini della funzione in cui si trovano. Se non sono in una funzione, sono globali.

function usaVar() {
    if (true) {
        var messaggio = "Sono accessibile ovunque nella funzione!";
    }
    // Nessun errore: var scavalca il blocco if!
    console.log(messaggio); 
}

1.2 let e const: Scope di Blocco (Il recinto sicuro)

Con let e const, le variabili nascono e muoiono all’interno delle parentesi graffe {} in cui sono dichiarate. Questo comportamento (Block Scope) previene fughe di dati involontarie.

function usaLet() {
    if (true) {
        let segreto = "Non puoi leggermi fuori";
    }
    // ❌ Errore: segreto is not defined
    // console.log(segreto); 
}

1.3 Il Bug del Loop: Perché var ti tradisce nell’asincrono

Questa è la classica domanda da colloquio tecnico. La differenza di scope diventa critica quando usi callback asincrone e closure (come setTimeout) dentro un ciclo.

Il problema con var:
Poiché var non ha scope di blocco, la variabile i è condivisa tra tutte le iterazioni. Quando il timer scatta (dopo 1 secondo), il ciclo è già finito e tutte le callback leggono lo stesso valore finale.

// ❌ Esempio errato con VAR
for (var i = 0; i < 3; i++) {
    // 'i' è la stessa variabile per tutti!
    setTimeout(() => console.log("Var: " + i), 1000);
}
// Output disastroso: "Var: 3", "Var: 3", "Var: 3"

La soluzione con let:
Grazie allo scope di blocco, let crea una nuova associazione per la variabile in ogni singola iterazione. Ogni timer “ricorda” il valore esatto di quel giro.

// ✅ Esempio corretto con LET
for (let i = 0; i < 3; i++) {
    // Una nuova 'i' viene creata per ogni iterazione
    setTimeout(() => console.log("Let: " + i), 1000);
}
// Output corretto: "Let: 0", "Let: 1", "Let: 2"

2. Hoisting e Temporal Dead Zone (TDZ)

L’Hoisting (sollevamento) è il comportamento del motore JavaScript che “sposta” le dichiarazioni in cima al loro scope. Per una definizione tecnica formale puoi consultare il glossario MDN sull’Hoisting. Ma c’è una sfumatura vitale da comprendere.

2.1 Var: Hoisting con inizializzazione

Con var, la variabile viene sollevata e inizializzata subito a undefined. Questo permetteva codice disordinato e buggato:

console.log(auto); // undefined (Nessun errore, ma dato sporco)
var auto = "Fiat";

2.2 Let/Const: La Temporal Dead Zone

Molti pensano che let e const non subiscano hoisting. Falso. Vengono sollevate, ma non inizializzate.

Il periodo di tempo tra l’ingresso nello scope e la dichiarazione effettiva si chiama Temporal Dead Zone (TDZ). Se provi a toccare la variabile nella TDZ, JavaScript lancia un errore, proteggendoti.

{
  // 💀 INIZIO TDZ
  // console.log(piatto); // ReferenceError: Cannot access before initialization

  let piatto = "Pasta"; // 🏁 FINE TDZ - La variabile ora è sicura
  console.log(piatto); // "Pasta"
}

3. Mutabilità e Gestione della Memoria

Quando usare let e quando const? La risposta sta nella mutabilità.

3.1 Const: un binding di sola lettura, non un valore immutabile

const è una parola chiave riservata di JavaScript che crea un legame (binding) di sola lettura. Una volta assegnato un valore, quel binding non può essere riassegnato. Questo può essere paragonato a const int nei linguaggi a tipizzazione statica come C o Java, con una differenza fondamentale: in JavaScript il valore puntato può comunque mutare se è un oggetto. Anche MDN raccomanda di usare const per default ogni volta che una variabile non viene riassegnata.

const TASSA = 22;
// TASSA = 25; // TypeError: Assignment to constant variable.

3.2 Il trucco degli Oggetti (Reference vs Value)

Attenzione: const blocca l’assegnazione, ma non congela il valore se questo è un oggetto o un array. In termini di memoria: protegge l’indirizzo di casa, ma non ti impedisce di cambiare l’arredamento interno.

const utente = { nome: "Mario" };

// ❌ ERRORE: Non puoi cambiare il riferimento (l'indirizzo)
// utente = { nome: "Luigi" }; 

// ✅ OK: Puoi modificare il contenuto all'interno!
utente.nome = "Luigi"; 
console.log(utente.nome); // "Luigi"

Se hai bisogno di un oggetto davvero immutabile, puoi usare Object.freeze():

const utente = Object.freeze({ nome: "Mario" });
utente.nome = "Luigi"; // Silenziosamente ignorato in strict mode
console.log(utente.nome); // "Mario"

4. Best Practices per il 2026

Come scrivere codice pulito oggi? Segui questa semplice gerarchia:

Default: const. Usa sempre const come prima scelta. Rende il codice più leggibile perché comunica che quel valore non dovrebbe cambiare. In React, ad esempio, tutti i hook devono essere dichiarati con const (const [stato, setStato] = useState(null)).

Opzione B: let. Usa let solo se sai per certo che il valore dovrà cambiare — contatori di loop, accumulatori, variabili che cambiano a seguito di una condizione.

Mai: var. Non c’è quasi nessun motivo valido per usare var nel codice moderno. L’unica eccezione possibile è il lavoro su codice legacy molto datato che non può essere refactorizzato.


5. Errori Comuni da Evitare

Anche sviluppatori esperti cadono in questi pattern. Ecco i più frequenti con la soluzione corretta.

Errore 1: Usare var in un ciclo con callback asincrone

Come visto nella sezione 1.3, var in un loop asincrono produce valori inaspettati. La soluzione è sempre let.

Errore 2: Dichiarare variabili con var nello scope globale

// ❌ Sbagliato — inquina l'oggetto window
var appName = "MyApp";
console.log(window.appName); // "MyApp" — pericoloso!

// ✅ Corretto — rimane nello scope del modulo
const appName = "MyApp";
console.log(window.appName); // undefined — sicuro

Errore 3: Confondere const con immutabilità totale

// ❌ Pensiero sbagliato
const config = { debug: false };
// "Non posso cambiare nulla perché è const"

// ✅ Realtà: il contenuto dell'oggetto può essere modificato
config.debug = true; // Funziona perfettamente!
// Solo config = { ... } darebbe errore

Errore 4: Accedere a una variabile let/const prima della dichiarazione

// ❌ Sbagliato — TDZ attiva
console.log(valore); // ReferenceError
let valore = 42;

// ✅ Corretto — dichiara sempre prima di usare
let valore = 42;
console.log(valore); // 42

6. FAQ — Domande Frequenti

Quando usare let invece di const?

Usa let quando sai che il valore della variabile dovrà cambiare durante l’esecuzione del programma: contatori, accumulatori, variabili aggiornate in base a condizioni. In tutti gli altri casi preferisci const.

var è deprecato in JavaScript?

Formalmente no: var è ancora una parola chiave valida nel linguaggio di programmazione JavaScript e non è stata rimossa. In pratica però è considerata legacy da tutti i moderni standard di scrittura del codice (ESLint, Airbnb Style Guide, Google Style Guide). Non deve essere usata nel codice moderno.

const rende un oggetto completamente immutabile?

No. const crea un binding di sola lettura: non puoi riassegnare la variabile, ma il contenuto dell’oggetto o dell’array a cui punta può essere modificato. Per un’immutabilità totale devi usare Object.freeze().

Qual è la differenza tra scope di funzione e scope di blocco?

Lo scope di funzione (usato da var) rende la variabile visibile in tutta la funzione, indipendentemente da dove viene dichiarata. Lo scope di blocco (usato da let e const) limita la visibilità alle sole parentesi graffe {} in cui la variabile è stata dichiarata.

Cosa succede se uso var fuori da qualsiasi funzione?

La variabile diventa globale e viene aggiunta direttamente all’oggetto window del browser. Questo può causare collisioni con librerie esterne o altri script e viene definito “global pollution”. Con let e const dichiarate allo stesso livello, questo non accade.


Conclusione

Passare da var a let e const è stato uno dei più grandi salti di qualità nella storia di JavaScript come linguaggio di programmazione. Hai guadagnato scope prevedibili, sicurezza contro gli errori di digitazione grazie alla TDZ e una gestione più chiara della memoria.

Ora che sai come dichiarare le variabili nel modo corretto, il passo successivo naturale è capire come JavaScript gestisce il sollevamento delle dichiarazioni a un livello più profondo: trovi tutto nell’articolo su Hoisting JavaScript. Se invece vuoi applicare subito questi concetti in un contesto reale, la guida su Clean Code in JavaScript ti mostrerà pattern pratici per scrivere codice professionale.