Introduzione
Quando si studiano le variabili JavaScript, non è sufficiente sapere che possono contenere stringhe, numeri, booleani, null o undefined. È altrettanto importante capire dove una variabile può essere utilizzata e per quanto tempo rimane disponibile. Questi concetti prendono il nome di scope e lifetime.
Lo scope, cioè l’ambito di visibilità, determina il punto del programma in cui una variabile è accessibile. La durata, invece, indica per quanto tempo quella variabile esiste durante l’esecuzione del codice. Comprendere questi meccanismi aiuta a evitare errori come l’uso di variabili non accessibili, sovrascritture accidentali e riferimenti a variabili dichiarate troppo tardi.
In JavaScript moderno si usano principalmente let e const. Entrambe sono dichiarazioni con block scope: una variabile è disponibile solamente all’interno del blocco delimitato da parentesi graffe, come un’istruzione if, un ciclo o una funzione. La parola chiave var, invece, segue regole più vecchie e può produrre comportamenti meno intuitivi.
Codice completo
// Le variabili dichiarate con let e const hanno block scope
const messaggio = "Valore globale";
function mostraScope(utenteAttivo) {
// Questa variabile esiste solo dentro la funzione
const nomeUtente = "Giulia";
if (utenteAttivo) {
// Questa variabile esiste solo dentro il blocco if
let stato = "online";
console.log(messaggio); // Accessibile
console.log(nomeUtente); // Accessibile
console.log(stato); // Accessibile
}
// Errore: stato è fuori dal suo blocco
// console.log(stato);
// La variabile dichiarata con var non rispetta il block scope
if (utenteAttivo) {
var ruolo = "editor";
}
// Funziona, perché var ha scope di funzione
console.log(ruolo);
}
mostraScope(true);
// La Temporal Dead Zone impedisce l´uso prima della dichiarazione
function calcolaPrezzo() {
// Errore: prezzo è nella Temporal Dead Zone
// console.log(prezzo);
const prezzo = 25;
return prezzo;
}
console.log(calcolaPrezzo()); Spiegazione
Scope globale e scope locale
Una variabile dichiarata fuori da funzioni e blocchi appartiene allo scope globale del file o del modulo. Nel codice dell’esempio, messaggio è accessibile dentro mostraScope, perché uno scope interno può leggere i valori presenti in uno scope esterno.
Il contrario non è valido: una variabile locale non può essere utilizzata dall’esterno. nomeUtente è stata dichiarata dentro la funzione, quindi non può essere letta dopo la chiamata a mostraScope. Questo isolamento è utile perché impedisce alle funzioni di modificare accidentalmente variabili appartenenti ad altre parti dell’applicazione.
Il block scope di let e const
Un blocco è qualsiasi sezione racchiusa tra parentesi graffe. Per esempio, il corpo di un’istruzione if o di un ciclo for è un blocco. Una variabile dichiarata con let o const rimane confinata a quel blocco.
Nel codice, stato viene creata solamente quando utenteAttivo è vero. Anche in questo caso, però, la variabile non è disponibile dopo la parentesi graffa di chiusura dell’if. Se si prova a eseguire console.log(stato), JavaScript genera un ReferenceError.
Perché var può creare problemi
var ha function scope, non block scope. Questo significa che una variabile dichiarata dentro un if rimane disponibile per tutta la funzione che contiene quel blocco. Per questo motivo ruolo può essere utilizzata anche dopo l’istruzione if.
Questo comportamento era comune nel JavaScript precedente a ES2015, ma oggi può rendere il codice più difficile da prevedere. In generale, è preferibile usare const quando il riferimento non deve essere riassegnato e let quando il valore deve cambiare.
Temporal Dead Zone
Le variabili dichiarate con let e const vengono registrate all’interno del loro scope, ma non possono essere utilizzate prima della riga di dichiarazione. L’intervallo tra l’inizio dello scope e la dichiarazione prende il nome di Temporal Dead Zone, abbreviata in TDZ.
Per esempio, nel caso di prezzo, la chiamata a console.log(prezzo) posta prima di const prezzo = 25 causerebbe un errore. La TDZ è una protezione utile: obbliga a dichiarare le variabili prima di utilizzarle e rende più chiara la sequenza logica del programma.
Scope lessicale e funzioni annidate
JavaScript utilizza lo scope lessicale. Una funzione può accedere alle variabili definite nel punto del codice in cui è stata dichiarata, anche se viene eseguita in un altro contesto. Questo comportamento è alla base delle closure.
function creaContatore() {
let valore = 0;
return function () {
valore++;
return valore;
};
}
const contatore = creaContatore();
console.log(contatore()); // 1
console.log(contatore()); // 2 La funzione interna continua ad accedere a valore anche dopo la fine di creaContatore. Il valore viene mantenuto perché la funzione conserva un riferimento al proprio ambiente lessicale.
Best practice
- Usa
constcome scelta predefinita quando una variabile non deve essere riassegnata. - Usa
letsolo quando il valore deve cambiare, per esempio in un contatore. - Evita
varnel codice moderno, salvo esigenze specifiche di compatibilità con codice legacy. - Dichiara le variabili prima del loro utilizzo per evitare problemi legati alla Temporal Dead Zone.
- Mantieni le variabili nello scope più piccolo possibile: riduce conflitti e rende il codice più facile da testare.
- Non creare inutilmente variabili globali: possono essere modificate da molte parti dell’applicazione.
- Usa nomi descrittivi, come
prezzoTotaleoutenteAutenticato, invece di nomi generici comexodato.
Riepilogo
Lo scope stabilisce dove una variabile può essere usata, mentre la sua durata indica per quanto tempo rimane disponibile durante l’esecuzione. let e const rispettano il block scope e sono gli strumenti consigliati nel JavaScript moderno. var ha invece function scope e può rendere meno prevedibile l’accessibilità delle variabili.
La Temporal Dead Zone impedisce di leggere una variabile dichiarata con let o const prima della sua dichiarazione. Applicando queste regole, si ottiene codice più sicuro, leggibile e semplice da mantenere.
Approfondisci con risorse ufficiali
Per approfondire questi argomenti, consulta la documentazione MDN dedicata alle dichiarazioni di variabili JavaScript, allo scope e alle closure. È utile anche leggere la specifica ECMAScript, disponibile sul sito ufficiale ecma-international.org, per studiare il comportamento formale di let, const, var e degli ambienti lessicali.
