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 impari a imparare JavaScript e a utilizzare di più le variabili.

L'ambito può aiutarti a:

  • Utilizza la memoria in modo più efficiente:l'ambito offre la possibilità di caricare le variabili solo quando necessario. Se una variabile non rientra nell'ambito, non è necessario renderla disponibile per il codice attualmente in esecuzione.
  • Individuazione e correzione più semplice dei bug: isolare le variabili con l'ambito locale semplifica la risoluzione dei bug nel codice in quanto, a differenza delle variabili globali, puoi avere 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 con modifiche minime.

Che cos'è l'ambito?

L'ambito di una variabile determina la posizione all'interno del codice in cui puoi utilizzare una variabile.

JavaScript definisce variabili di ambito globale o locale:

  • Le variabili con ambito globale sono disponibili da 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 vengono 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, la variabile ha un ambito locale.

Le sezioni successive di questo articolo trattano l'ambito a blocchi e grammaticali:

  • Le variabili di ambito dei blocchi sono disponibili localmente per un blocco, come determinato 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 legislativo utilizza la posizione in cui viene dichiarata una variabile nel codice sorgente per determinare dove è disponibile. Puoi utilizzare le chiusure per concedere a una funzione inclusa l'accesso alle variabili a cui viene fatto riferimento nell'ambito esterno noto come ambiente lessicale.

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

Per dichiarare una variabile:

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

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

Esempi di ambito

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

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

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

Questo esempio dimostra l'ambito locale perché dichiara la variabile greeting con la parola chiave let all'interno di una funzione. La variabile greeting è una variabile 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 dei blocchi perché dichiara la variabile greeting all'interno di un blocco in modo che la variabile 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 l'ambito del blocco e il blocco più vicino fa parte dell'istruzione condizionale if. Non puoi accedere dall'esterno di un blocco alle variabili let e const che hai dichiarato all'interno di un blocco. Di conseguenza, puoi accedere solo alla variabile greeting all'interno delle parentesi graffe, che specifica l'ambito del blocco.

Questo esempio corregge l'errore perché il metodo console.log(message) viene spostato 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.

Considera 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, puoi accedere al valore della variabile globalMessage da qualsiasi punto del programma JavaScript.

Puoi visualizzare i contenuti dei file file-1.js e file-2.js in questo snippet di codice. 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 approfondito in questo articolo. Se crei una variabile all'interno di un modulo JavaScript, ma al di fuori di una funzione o di un blocco, l'ambito non è globale, bensì un ambito del modulo. Le variabili con ambito del modulo sono disponibili ovunque all'interno del modulo corrente, ma non sono disponibili in altri file o moduli. Per rendere disponibile una variabile con ambito a livello di modulo per altri file, devi esportarla dal modulo in cui è stata creata e quindi 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 rispetto alla funzione, quindi puoi accedervi solo dall'interno della funzione. Le variabili locali vengono create all'avvio di una funzione e vengono eliminate 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 per la variabile name e il relativo valore "Elizabeth" sono contenuti tra parentesi graffe. Le variabili in un ambito dei blocchi non sono disponibili al di fuori del blocco.

{
    const name = "Elizabeth";
}

Puoi utilizzare variabili con ambito a blocchi all'interno di istruzioni if, for o while.

Prendi nota dei due loop for all'interno di questo snippet di codice. Un ciclo for utilizza la parola chiave var per dichiarare la variabile inizializzatore, che aumenta di conseguenza i numeri 0, 1 e 2. L'altro ciclo for utilizza la parola chiave let per dichiarare la variabile inizializzatore.

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.

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

Riutilizzo di un nome 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 come l'utilizzo dell'ambito ti consenta 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, quindi non sono in conflitto tra loro.

Chiusure e ambito normativo

Le chiusure si riferiscono a una funzione inclusa in cui una funzione interna può accedere all'ambito della funzione esterna, noto anche come ambiente lessicale. Pertanto, in JavaScript, si utilizzano le chiusure per consentire alle funzioni di fare riferimento all'ambiente didattico esterno, consentendo al codice all'interno di una funzione di fare riferimento a variabili dichiarate al di fuori della funzione. Infatti, è possibile programmare 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 didattico che viene creato quando viene richiamata la funzione outer(), che si chiude sulla 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 durante il runtime. Per scoprire di più sull'ambiente lessicale, consulta Definizione dell'ambito e chiusura terminologica.

Moduli

I moduli JavaScript consentono di organizzare il codice JavaScript. Se utilizzati correttamente, forniscono una struttura efficace al codebase e facilitano il riutilizzo del codice. Anziché utilizzare variabili globali per condividere variabili tra file diversi, 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 ambiti, puoi provare a scrivere codice con JS Scope Visualizer. La demo utilizza la colorazione nel codice per aiutarti a visualizzare gli ambiti JavaScript.

Conclusione

Questo articolo introduce diversi tipi di ambito. L'ambito JavaScript è uno dei concetti più avanzati nell'ambito dello sviluppo web, pertanto è fantastico che tu abbia letto questi contenuti e che tu abbia avuto tempo per comprendere l'argomento.

L'ambito non è una funzionalità rivolta agli utenti. Riguarda solo lo sviluppatore web che scrive il codice, ma conoscere il funzionamento dell'ambito può aiutarti a correggere i bug non appena si presentano.