Scope delle Variabili in JavaScript
Dev

Scope delle Variabili in JavaScript

Video sullo scope delle variabili javascript
☝ Occhio che questo porta a YouTube

Nel senso più generale del termine lo scope fa riferimento al contesto di esecuzione. Il contesto è quello dove valori ed espressioni sono “visibili” e possono essere referenziati.

Se una variabile non si trova nello scope corrente, non sarà disponibile. Lo scope può essere gerarchizzato, in modo tale che gli scope figli abbiano accesso al padre, ma non vice versa.

In JavaScript sono presenti tre tipi di scope:

  • globale: quello scope disponibile ovunque all'interno dello script
  • locale: si fa riferimento allo scope delle funzioni. Le variabili dichiarate all'interno di una funzione esistono solo in quest'ultima e non sono accessibili dall'esterno.
  • blocco: le variabili dichiarate tra una coppia di parentesi graffe, saranno disponibili solo tra queste e verranno distrutte non appena verrà superata la parentesi di chiusura. NB: Non sono le istruzioni come if e for a creare lo scope di blocco, ma la parola chiave let o const usata per dichiarare rispettivamente una variabile o una costante. Contrariamente la parola chiave var non supporta questo tipo di scope.

Lo scope globale

Dal momento in cui inizi a scrivere un documento JavaScript ti trovi nello scope globale. Di questo ce n'è solo uno in tutto il documento. Una variabile nello scope globale è definita al di fuori di una funzione.

1// Lo scope è globale di default 2var nome = "Manuel";

Le variabili presenti nello scope globale possono essere utilizzate e alterate da qualsiasi altro scope. Sono disponibili ovunque.

1var nome = "Manuel"; 2 3console.log(nome); // Mostra in console 'Manuel' 4 5function saluta() { 6 console.log(nome); // 'nome' è accessibile all'interno della funzione, come in qualunque altro punto dello script. 7} 8 9saluta(); // Mostra in console 'Manuel'

Lo scope locale

Le variabili definite all'interno del corpo di una funzione sono nello scope locale. Ogni funzione ha il suo scope. Ciò significa che variabili con lo stesso nome, utilizzate in funzioni differenti, non andranno in conflitto. Questo perché ogni variabile è legata alla sua rispettiva funzione. Lo scope locale non è accessibile dall'esterno della funzione.

1// Scope globale 2function paperino() { 3 // Scope locale #1 4 function pippo() { 5 // Scope locale #2 6 } 7} 8 9// Scope globale 10function topolino() { 11 // Scope locale #3 12}

Lo scope di blocco

Come menzionato in precedenza le istruzioni if, switch, for e while a differenza delle funzioni non creano un proprio scope.

1if (true) { 2 // non viene creato un nuovo scope 3 var nome = "Manuel"; // 'nome' è presente nello scope globale 4} 5 6console.log(nome); // Mostra in console 'Manuel'

Ma allora, come si può sfruttare lo scope di blocco? Come già anticipato, ECMAScript 6 ha introdotto due nuove parole chiave, let e const. Il cui compito è quello di creare variabili e costanti (la differenza è abbastanza ovvia), ma non solo. let e const a differenza di var supportano la dichiarazione di uno scope di blocco all'interno di un'istruzione come quelle elencate in precedenza. In pratica, la variabile o la costante dichiarata con le apposite keyword all'interno, ad esempio, di un blocco if, esisterà fino a quando non verrà raggiunta la parentesi graffa di chiusura del blocco.

1if (true) { 2 // come prima niente nuovo scope. 3 // 'nome' è presente nello scope globale perché dichiarata con var 4 var nome = "Manuel"; 5 // 'hobby' è nello scope locale grazie alla keyword let 6 let hobby = "Gaming"; 7 // 'giocoPreferito' è nello scope locale grazie alla keyword const 8 const giocoPreferito = "Halo"; 9} // qui 'hobby' e 'giocoPreferito' smettono di esistere. 10 11console.log(nome); // Mostra in console 'Manuel' 12console.log(hobby); // Uncaught ReferenceError: hobby is not defined 13console.log(giocoPreferito); // Uncaught ReferenceError: giocoPreferito is not defined

Lo scope può essere annidato

Una peculiarità da non dimenticare dello scope è che può essere annidato.

1function chiamaBatman() { 2 // scope locale della funzione 3 let batsegnale = "spento"; 4 5 if (batsegnale === "spento") { 6 // scope di blocco 7 const sidekick = "Robin"; 8 batsegnale = "acceso"; 9 console.log(batsegnale); // 'acceso' 10 } 11 12 console.log(sidekick); // Uncaught ReferenceError: sidekick is not defined 13} 14 15chiamaBatman();

Lexical Scope o Static Scoping

Per concludere questo breve video introduttivo sullo scope in JavaScript, di concetti ce ne sarebbero ancora a tonnellate, ma mi sono ripromesso di fare video più brevi, ci rimane solo da comprendere il lexical scope o static scoping. Di che cosa si tratta?

Definiamo due funzioni, innerFunc() è annidata in outerFunc().

1function outerFunc() { 2 // outerFunc scope 3 let outerVar = "Sono fuori"; 4 function innerFunc() { 5 // innerFunc scope 6 console.log(outerVar); // "Sono fuori" 7 } 8 return innerFunc; 9} 10const inner = outerFunc(); 11inner();

Come fa a funzionare?

Risposta breve: grazie al lexical scope

Risposta lunga: JavaScript implementa un meccanismo di scoping chiamato lexical scope (o static scoping). Ciò significa che l’accesso alle variabili è determinato staticamente dalla posizione delle stesse all'interno dello scope della funzione nidificata. Per cui la funzione interna può accedere alle variabili dello scope della funzione esterna.

Nel nostro esempio, il lexical scope di innerFunc() è costituito dallo scope di outerFunc(). Andando più nello specifico innerFunc() è quella che viene definita una closure, ma ripeto, mi sono ripromesso di fare video più brevi. Le closure e tutte le menate collegate saranno oggetto di un altro video.

Conclusione

Con questo dovresti riuscire a consolidare le tue basi sulle scoping delle variabili in JavaScript, se hai dubbi o domande, contattami. Non dimenticare di iscriverti al canale per rimanere sempre aggiornato sui nuovi video.

Grazie per la visione (lettura in questo caso), stay safe.

Crediti foto: Will Francis

;