Lezione 3 — Variabili in JavaScript: Guida Completa a let, const e var

Scopri come gestire i dati in JavaScript. Impara la differenza tra let, const e var, comprendi lo scope e le best practice per scrivere codice moderno e sicuro.

Introduzione alle Variabili in JavaScript

Benvenuti alla terza lezione del nostro corso "Impara JavaScript in 50 lezioni". In questa sessione ci immergeremo in uno dei concetti più fondamentali di qualsiasi linguaggio di programmazione: le variabili.

Immaginate una variabile come una scatola etichettata in cui potete conservare un valore. Questo valore potrebbe essere un numero, una stringa di testo, un oggetto complesso o un valore booleano (vero/falso). Durante l'esecuzione di un programma, il contenuto di questa scatola può essere letto, utilizzato per eseguire calcoli o modificato per riflettere un cambiamento di stato nell'applicazione.

Per anni, JavaScript ha offerto un unico modo per dichiarare variabili: la parola chiave var. Tuttavia, con l'introduzione di ES6 (ECMAScript 2015), il linguaggio ha fatto un salto evolutivo introducendo let e const. Questa evoluzione non è stata solo sintattica, ma ha risolto problemi strutturali profondi legati a come JavaScript gestisce la memoria e la visibilità dei dati (lo cosiddetto "scope").

La dichiarazione classica: var

Prima del 2015, var era l'unico strumento a disposizione degli sviluppatori. Sebbene sia ancora supportata da tutti i browser per motivi di retrocompatibilità, oggi è considerata obsoleta e sconsigliata nella maggior parte dei casi.

Come funziona var

Quando dichiariamo una variabile con var, JavaScript la crea con uno scope di funzione. Ciò significa che se la variabile è dichiarata all'interno di una funzione, è visibile ovunque in quella funzione. Se invece è dichiarata all'esterno, diventa una variabile globale.

Uno dei problemi principali di var è l'assenza di "block scope" (scope di blocco). In linguaggi come Java o C++, una variabile dichiarata all'interno di un ciclo if o for esiste solo all'interno di quel blocco. In JavaScript, con var, questo non accade.

Ecco un esempio per illustrare il comportamento problematico di var:

if (true) {
    var nome = "Mario";
    console.log("Dentro il blocco: " + nome);
}

// Sorpresa! La variabile è accessibile anche fuori dal blocco if
console.log("Fuori dal blocco: " + nome); 

In questo codice, nonostante nome sia stata dichiarata dentro le parentesi graffe del blocco if, essa "scivola" all'esterno, diventando accessibile in tutto lo script. Questo può portare a bug difficili da scovare, specialmente in progetti di grandi dimensioni dove diverse parti del codice potrebbero accidentalmente sovrascrivere la stessa variabile.

La rivoluzione di let: Scope di Blocco

Per risolvere i limiti di var, ES6 ha introdotto let. Questa parola chiave permette di dichiarare variabili che hanno uno "scope di blocco". Un blocco è definito da qualsiasi coppia di parentesi graffe { ... }.

Perché usare let?

let è la scelta predefinita quando sappiamo che il valore di una variabile dovrà cambiare nel tempo. A differenza di var, se dichiariamo una variabile con let all'interno di un ciclo o di una condizione, essa rimarrà confinata in quell'area.

Vediamo come cambia l'esempio precedente utilizzando let:

if (true) {
    let saluto = "Ciao Mondo!";
    console.log("Dentro il blocco: " + saluto);
}

// Questo genererà un errore: ReferenceError: saluto is not defined
try {
    console.log("Fuori dal blocco: " + saluto);
} catch (e) {
    console.log("Errore catturato: la variabile non esiste fuori dal blocco!");
}

Questo comportamento rende il codice molto più prevedibile. Se una variabile serve solo per un calcolo temporaneo all'interno di un ciclo for, usare let garantisce che quella variabile non inquini il resto del programma una volta che il ciclo è terminato.

L'immutabilità con const

L'ultima parola chiave a nostra disposizione è const, abbreviazione di "costante". Come suggerisce il nome, const viene utilizzata per dichiarare variabili il cui valore non deve essere riassegnato dopo l'inizializzazione.

Quando usare const?

La regola d'oro dello sviluppo moderno in JavaScript è: usa const per default, usa let solo se sai che il valore cambierà, e non usare mai var.

Usare const comunica agli altri sviluppatori (e a te stesso in futuro) che quel valore è stabile. Questo riduce il carico cognitivo durante la lettura del codice: se vedi const, sai che non devi preoccuparti che quel valore venga cambiato accidentalmente in un'altra parte del file.

const PI_GRECO = 3.14159;
const URL_API = "https://api.esempio.com/v1";

// Tentativo di riassegnazione
// PI_GRECO = 3.14; // Questo causerebbe un TypeError: Assignment to constant variable.

console.log("Il valore di PI è: " + PI_GRECO);

Importante: const e gli Oggetti

C'è un dettaglio fondamentale che spesso confonde i principianti: const impedisce la riassegnazione della variabile, ma non rende l'oggetto o l'array immutabile.

Se assegni un array a una costante, non puoi sostituire l'intero array con un altro, ma puoi comunque modificare gli elementi all'interno di quell'array.

const colori = ["Rosso", "Verde"];

// Questo è permesso: stiamo modificando il contenuto dell'array
colori.push("Blu");
console.log(colori); // ["Rosso", "Verde", "Blu"]

// Questo NON è permesso: stiamo cercando di cambiare l'identità della variabile
// colori = ["Giallo"]; // Errore!

Confronto Tecnico: Hoisting e Temporal Dead Zone

Per capire davvero la differenza tra var, let e const, dobbiamo parlare di un concetto avanzato chiamato Hoisting.

L'Hoisting di var

In JavaScript, le dichiarazioni var vengono "sollevate" (hoisted) all'inizio della loro funzione o dello script. Questo significa che puoi leggere una variabile var prima ancora di averla dichiarata nel codice, anche se il valore sarà undefined.

La Temporal Dead Zone (TDZ) di let e const

let e const sono anch'esse sollevate, ma a differenza di var, non vengono inizializzate. Questo crea un'area chiamata "Temporal Dead Zone". Se provi ad accedere a una variabile let o const prima della riga in cui è dichiarata, JavaScript lancerà un errore di riferimento (ReferenceError).

Questo è un comportamento positivo: costringe lo sviluppatore a scrivere codice ordinato, dichiarando le variabili prima di utilizzarle, evitando bug silenziosi e comportamenti imprevedibili.

Esempi Pratici e Casi d'Uso

Vediamo ora come applicare queste conoscenze in scenari reali di programmazione web.

Scenario 1: Gestione di un carrello acquisti

Immaginiamo di dover gestire un carrello. L'ID dell'utente non cambierà mai durante la sessione, mentre il totale del carrello sì.

const userId = "USER_12345"; // Costante: l'utente non cambia
let cartTotal = 0; // Let: il totale aumenterà con ogni prodotto aggiunto

function aggiungiProdotto(prezzo) {
    cartTotal += prezzo;
    console.log(`Prodotto aggiunto. Nuovo totale: ${cartTotal}€`);
}

aggiungiProdotto(19.99);
aggiungiProdotto(5.50);

console.log(`Utente ${userId} ha speso in totale ${cartTotal}€`);

Scenario 2: Cicli di iterazione

Quando usiamo un ciclo for, l'indice i cambia a ogni iterazione. Pertanto, let è la scelta obbligata.

const frutti = ["Mela", "Banana", "Arancia"];

for (let i = 0; i < frutti.length; i++) {
    console.log(`Frutto n. ${i + 1}: ${frutti[i]}`);
}
// Qui 'i' non esiste più, mantenendo pulito lo scope globale

Errori Comuni e FAQ

Domanda: Posso dichiarare due variabili con lo stesso nome?

Con var, sì. Se dichiari var x = 10 e poi var x = 20, JavaScript non dirà nulla. Con let e const, invece, riceverai un errore: SyntaxError: Identifier 'x' has already been declared. Questo è un enorme vantaggio perché impedisce di sovrascrivere variabili per errore.

Domanda: Quando dovrei usare let invece di const?

Usa let solo quando sai con certezza che il valore della variabile deve essere riassegnato. Se non sei sicuro, inizia con const. Se in seguito ti rendi conto che devi cambiare il valore, puoi tranquillamente cambiare la dichiarazione in let.

Errore comune: Dimenticare l'inizializzazione di const

Una variabile var o let può essere dichiarata senza un valore iniziale (sarà undefined). Una const deve essere inizializzata al momento della dichiarazione.

let x;
const y; // Errore: Missing initializer in const declaration

Prossimi Passi

Ora che hai padroneggiato la gestione delle variabili, sei pronto per esplorare come manipolare i dati contenuti in esse. Nella prossima lezione parleremo dei Tipi di Dato in JavaScript, dove scopriremo la differenza tra Stringhe, Numeri, Booleani, Null e Undefined.

Per approfondire l'argomento di oggi, ti consiglio di:

  1. Aprire la console del browser (F12 -> Console) e provare a dichiarare variabili con var, let e const per osservare gli errori di scope.
  2. Leggere la documentazione ufficiale di MDN (Mozilla Developer Network) sulla sezione "Grammar and Types".
  3. Provare a riscrivere un vecchio pezzo di codice che usava var convertendolo in let e const per vedere se si rompe qualcosa.

Ricorda: la programmazione è un'arte che si impara facendo. Non limitarti a leggere, scrivi codice!