Ambito della variabile globale e locale

Questo articolo fornisce informazioni sull'ambito e sul suo funzionamento in JavaScript.

L'ambito è un concetto fondamentale in JavaScript e in altri linguaggi di programmazione che definisce il contesto in cui viene eseguito l'accesso e l'utilizzo delle variabili. Diventa più utile e applicabile al tuo codice man mano che continui ad apprendere JavaScript e a lavorare di più con le variabili.

L'ambito può aiutarti a:

  • Utilizza la memoria in modo più efficiente: l'ambito consente di caricare le variabili solo quando necessario. Se una variabile non rientra nell'ambito, non è necessario renderla disponibile per il codice attualmente in esecuzione.
  • Individuare e correggere più facilmente i bug: isolare le variabili con ambito locale semplifica la risoluzione dei bug nel codice perché, a differenza delle variabili globali, hai la certezza che il codice proveniente da un ambito esterno non sia in grado di manipolare le variabili con ambito locale.
  • Crea piccoli blocchi di codice riutilizzabile: ad esempio, puoi scrivere una funzione pura che non si basa su un ambito esterno. Puoi spostare facilmente una funzione di questo tipo altrove apportando modifiche minime.

Che cos'è l'ambito?

L'ambito di una variabile determina da dove puoi utilizzare una variabile all'interno del codice.

JavaScript definisce le variabili di ambito globale o locale:

  • Le variabili con ambito globale sono disponibili in tutti gli altri ambiti all'interno del codice JavaScript.
  • Le variabili con ambito locale sono disponibili solo all'interno di un contesto locale specifico e sono create da parole chiave, come var, let e const. Se utilizzi le parole chiave var, let o const per creare una variabile all'interno di una funzione, tale variabile ha un ambito locale.

Le sezioni successive di questo articolo trattano degli ambiti a blocchi e lessicali:

  • Le variabili di ambito del blocco sono disponibili localmente per un blocco secondo quanto stabilito dalla posizione delle parentesi graffe in cui è definita l'istruzione di blocco. Solo le variabili dichiarate con le parole chiave let o const hanno l'ambito del blocco.
  • L'ambito lessicale utilizza la località in cui viene dichiarata una variabile nel codice sorgente per determinare dove è disponibile. Puoi utilizzare le chiusure per concedere a una funzione chiusa l'accesso alle variabili a cui viene fatto riferimento nell'ambito esterno noto come ambiente lexical.

Quando si accede a una variabile all'interno del suo ambito, JavaScript restituisce il valore assegnato oppure genera un errore.

Per dichiarare una variabile:

  • Utilizza le parole chiave var, const o let per dichiarare le variabili di ambito locale o globale.
  • Utilizza le parole chiave const o let per dichiarare le variabili dell'ambito a blocchi.

Quando dichiari una variabile var in una funzione, la dichiarazione la rende disponibile alla funzione di inclusione più vicina. Non puoi utilizzare la parola chiave var per dichiarare variabili con ambito a blocchi.

Esempi di ambiti

Questo esempio mostra l'ambito globale perché la variabile greeting è dichiarata al di fuori di qualsiasi funzione o blocco, il che rende disponibile il suo valore a tutto il codice nel documento corrente:

const greeting = 'hello';
console.log(greeting); // 'hello'

Nell'esempio con ambito globale, alla variabile greeting viene assegnato un valore hello.

Questo esempio mostra l'ambito locale perché dichiara la variabile greeting con la parola chiave let all'interno di una funzione. La variabile greeting è con ambito locale e non è disponibile al di fuori della funzione.

function greet() {
  let greeting = 'Hello World!';
  console.log(greeting);
}

Questo esempio mostra l'ambito a blocchi perché dichiara la variabile greeting all'interno di un blocco in modo che sia accessibile solo all'interno delle parentesi graffe:

if (true) {
   const greeting = 'hello';
}

console.log(greeting); // ReferenceError: greeting is not defined

Tieni presente che quando la funzione console.log tenta di restituire il valore della variabile greeting, JavaScript restituisce un messaggio di errore ReferenceError anziché il messaggio hello previsto. Perché?

Viene restituito un errore perché la variabile greeting ha un ambito di blocco e il blocco più vicino fa parte dell'istruzione condizionale if. Non puoi accedere alle variabili let e const dichiarate all'interno di un blocco dall'esterno di quest'ultimo. Pertanto, puoi accedere alla variabile greeting solo all'interno delle parentesi graffe, che specifica l'ambito del blocco.

Questo esempio corregge l'errore perché sposta il metodo console.log(message) all'interno delle parentesi graffe. Il codice aggiornato sposta il metodo console.log(message) all'interno del blocco.

if (true) {
   const greeting = 'hello';
   console.log(greeting);
}

Tipi di ambito

Ambito globale

Puoi accedere alle variabili con ambito globale da qualsiasi punto del programma.

Prendiamo in considerazione un file HTML che importa due file JavaScript: file-1.js e file-2.js:

<script src="file-1.js"></script>
<script src="file-2.js"></script>

In questo esempio, la variabile globalMessage ha un ambito globale ed è scritta al di fuori di una funzione. Durante l'esecuzione e l'esecuzione, puoi accedere al valore della variabile globalMessage da qualsiasi punto del programma JavaScript.

In questo snippet di codice puoi vedere i contenuti dei file file-1.js e file-2.js. Osserva la disponibilità della variabile globalMessage in entrambi i file.

// file-1.js
function hello() {
    var localMessage = 'Hello!';
}

var globalMessage = 'Hey there!';

// file-2.js
console.log(localMessage); // localMessage is not defined
console.log(globalMessage); // Hey there!

C'è un altro tipo di ambito che non è trattato in modo significativo in questo articolo. Se crei una variabile all'interno di un modulo JavaScript, ma al di fuori di una funzione o un blocco, questa non ha un ambito globale, bensì un modulo. Le variabili con ambito del modulo sono disponibili ovunque all'interno del modulo corrente, ma non in altri file o moduli. Per rendere disponibile in altri file una variabile con ambito modulo, devi esportarla dal modulo in cui è stata creata e poi import dal modulo che deve accedere alla variabile.

Ambito locale e ambito della funzione

Quando crei variabili in una funzione JavaScript con le parole chiave var, let o const, le variabili sono locali per la funzione, quindi puoi accedervi solo dall'interno della funzione. Le variabili locali vengono create all'avvio di una funzione e vengono eliminate di fatto al termine dell'esecuzione della funzione.

Questo esempio dichiara la variabile total nella funzione addNumbers(). Puoi accedere solo alle variabili a, b, e total all'interno della funzione addNumbers().

function addNumbers(a, b) {
    const total = a + b;
}

addNumbers(3, 4);

Puoi utilizzare le parole chiave let e const per assegnare un nome alle variabili. Quando utilizzi la parola chiave let, JavaScript può aggiornare la variabile. Tuttavia, con la parola chiave const, la variabile rimane costante.

var variable1 = 'Declared with var';
var variable1 = 'Redeclared with var';
variable1; // Redeclared with var

let variable2 = 'Declared with let. Cannot be redeclared.';
variable2 = 'let cannot be redeclared, but can be updated';
variable2; // let cannot be redeclared, but can be updated

const variable3 = 'Declared with const. Cannot be redeclared or updated';
variable3; // Declared with const. Cannot be redeclared or updated

Ambito del blocco

I blocchi vengono utilizzati per raggruppare una singola istruzione o un insieme di istruzioni. Puoi utilizzare le parole chiave const o let per dichiarare una variabile locale con ambito a blocchi. Tieni presente che non puoi utilizzare la parola chiave var per dichiarare le variabili con ambito a blocchi.

Ad esempio, in questo blocco, l'ambito della variabile name e il relativo valore "Elizabeth" sono contenuti all'interno delle parentesi graffe. Le variabili all'interno di un ambito del blocco non sono disponibili all'esterno del blocco.

{
    const name = "Elizabeth";
}

Puoi utilizzare variabili con ambito a blocchi nelle istruzioni if, for o while.

Prendi nota dei due loop for all'interno dello snippet di codice. Un ciclo for utilizza la parola chiave var per dichiarare la variabile di inizializzazione, che viene incrementata con i numeri 0, 1 e 2. L'altro loop for utilizza la parola chiave let per dichiarare la variabile di inizializzazione.

for (var i = 0; i < 2; i++) {
    // ...
}

console.log(i); // 2

for (let j = 0; j < 2; j++) {
    // ...
}

console.log(j); // The j variable isn't defined.

Nel precedente esempio di codice, potresti notare che la variabile i nel primo ciclo for è trapelata al di fuori del ciclo for e conserva comunque un valore 2 perché la parola chiave var non utilizza l'ambito a blocchi. Il problema è stato risolto nel secondo loop for in cui la variabile j dichiarata con la parola chiave let è limitata al blocco del loop for e non esiste al termine del loop for.

Riutilizzo del nome di una variabile in un ambito diverso

L'ambito può isolare una variabile all'interno di una funzione anche se riutilizzi lo stesso nome di variabile altrove in un ambito diverso.

Questo esempio mostra in che modo l'utilizzo dell'ambito ti consente di riutilizzare lo stesso nome di variabile in funzioni diverse:

function listOne() {
    let listItems = 10;
    console.log(listItems); // 10
}

function listTwo() {
   let listItems = 20;
   console.log(listItems); // 20
}

listOne();
listTwo();

Alle variabili listItems nelle funzioni listOne() e listTwo() vengono assegnati i valori previsti, pertanto non sono in conflitto tra loro.

Chiusure e ambito lessicale

Le chiusure fanno riferimento a una funzione racchiusa in cui una funzione interna può accedere all'ambito della funzione esterna, noto anche come ambiente lessicale. Quindi, in JavaScript, puoi usare le chiusure per consentire alle funzioni di fare riferimento all'ambiente lessicale esterno, il che consente al codice all'interno di una variabile di riferimento di una funzione dichiarata al di fuori della funzione. Infatti, puoi codificare una catena di riferimenti ad ambienti lessicali esterni in modo che una funzione venga chiamata da una funzione, che a sua volta viene chiamata da un'altra funzione.

In questo esempio, il codice forma una chiusura con l'ambiente lessicale che viene creato quando viene richiamata la funzione outer(), che si chiude sopra la variabile hello. Di conseguenza, la variabile hello viene utilizzata all'interno della funzione di callback setTimeout.

function outer() {
    const hello = 'world';

    setTimeout(function () {
        console.log('Within the closure!', hello)
    }, 100);
}

outer();

Con l'ambito lessicale, l'ambito viene determinato durante la compilazione del codice sorgente, non in fase di runtime. Per ulteriori informazioni sull'ambiente lessicale, consulta la sezione Ambito lessicale e chiusura.

Moduli

I moduli JavaScript sono utili per organizzare il codice JavaScript. Se usate correttamente, forniscono una struttura efficace al codebase e facilitano il riutilizzo del codice. Anziché utilizzare le variabili globali per condividere le variabili tra diversi file, i moduli JavaScript forniscono una tecnica per esportare e import le variabili.

// hello.js file
function hello() {
  return 'Hello world!';
}

export { hello };

// app.js file
import { hello } from './hello.js';

console.log(hello()); // Hello world!

Demo del visualizzatore ambito

L'ambito è un concetto fondamentale che ogni sviluppatore JavaScript dovrebbe comprendere. Per comprendere meglio il sistema di ambito, puoi provare a scrivere un codice personalizzato con JS Scope Visualizer. La demo utilizza la colorazione nel codice per aiutarti a visualizzare gli ambiti JavaScript.

Conclusione

Questo articolo illustra diversi tipi di ambito. L'ambito JavaScript è uno dei concetti più avanzati nell'ambito dello sviluppo web, quindi siamo lieti che tu abbia letto attentamente questi contenuti e che tu abbia dedicato del tempo alla comprensione di questo argomento.

L'ambito non è una funzionalità rivolta agli utenti. Il problema riguarda soltanto lo sviluppatore web che scrive il codice, ma sapere come funziona l'ambito può aiutarti a correggere eventuali bug.