Appunti Javascript per non Anglofoni
Esistono svariati libri e articoli su Javascript, e molti quindi staranno pensando che non se ne sentiva la mancanza… ma perlopiù parliamo di fonti in lingua inglese, gli appunti che che seguono — come forse avrete potuto notare ;) — saranno in lingua italiana.
Per poter comprendere gli appunti si presuppone una conoscenza basilare di Javascript, dei concetti di variabile, funzione, dichiarazioni condizionali e cicli.
LO SCOPE
Possiamo tradurre la parola Scope con Ambito/Contesto.
Lo scope o scope lessicale (lexical scope) è l’ambito nel quale vivono le variabili e le funzioni, al di fuori di quello che potremmo appunto chiamare contesto vitale non possiamo utilizzare una variabile o una funzione.
In Javascript esistono due tipi di scope, quello di Funzione e quello di Blocco, che è stato introdotto con ES6 ed è valido per le variabili dichiarate con let e const.
SCOPE DI FUNZIONE
Quando viene dichiarata una funzione si crea un nuovo scope valido all’interno del suo corpo, le variabili qui dichiarate non sono accessibili all’esterno, mentre la funzione può accedere alle variabili dichiarate nello scope genitore.
È importante tenere a mente che lo scope genitore è lo scope nel quale la funzione è stata dichiarata e non quella in cui è stata richiamata.
Facciamo un esempio:

HOISTING
Hoisting significa letteralmente Issare/Sollevare.
L’hoisting si riferisce alla peculiarità di Javascript di poter richiamare una funzione o una variabile dichiarata con var anche ad una riga precedente rispetto a quella dove è stata inserita, nello specifico di sollevare le funzioni e le variabili in cima allo scope corrente.
Grazie all’hoisting se utilizziamo una variabile dichiarata con var prima della dichiarazione non riceveremo un errore, ma il suo valore sarà undefined.

SCOPE DI BLOCCO
Come anticipato lo scope di blocco è stato introdotto con ES6 e funziona solo con le variabili dichiarate let e const.
Uno scope di blocco è creato all’interno delle parentesi graffe {}, ad esempio quando si dichiara un if, un ciclo o una funzione, oppure inserendo delle semplici parentesi graffe senza l’associazione di alcuna parola chiave.
Le variabili dichiarate all’interno di uno scope di blocco non sono soggette all’hoisting, quindi se proviamo ad utilizzarle prima della loro dichiarazione riceveremo un errore.
Le variabili dichiarate con let sono invece soggette a quella che è definita Temporal Dead Zone (TDZ), ossia il periodo di tempo che va dall’inizio del blocco alla dichiarazione della variabile.

VAR, LET E CONST
Guardiamo nel dettaglio le differenze tra le variabili dichiarate con var, let e const.
Le variabili dichiarate con var, come abbiamo già visto, sono soggette all’hoisting e possono essere riassegnate, ovvero possiamo cambiare il loro valore all’interno del nostro script, e possono essere ridichiarate senza generare errori.
Le variabili dichiarate con let, non sono soggette ad hoisting, ma sono soggette alla Temporal Dead Zone, possono essere riassegnate, ma non ridichiarate.
Ecco cosa succede se proviamo a ridichiarare una variabile let

Le variabili dichiarate con const, non sono soggette all’hoisting e non possono essere riassegnate, inoltre non possono essere dichiarate senza l’assegnazione contestuale di un valore.
Nel caso in cui sia loro assegnato come valore un array è possibile utilizzare su di esse tutti i metodi tipici degli array, come push(), pull() e map, come per gli object è possibile l’aggiunta, l’eliminazione o la riassegnazione delle chiavi.


Ma prima dell’introduzione di let e const?
IIFE
IMMEDIATELY INVOKED FUNCTION EXPRESSION
La IIFE è una Function Expression Immediatamente Invocata, si tratta di una funzione racchiusa tra parentesi tonde seguita da apertura e chiusura di parentesi tonde

Viene utilizzata per incapsulare il codice ed evitare che le variabili dichiarate al suo interno siano visibili nello scope globale.
Prendiamo questo esempio da https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/

Ci aspettiamo vengano stampati i tre valori dell’array, invece riceveremo tre undefined.
Perché?!
La funzione setTimeout crea una Closure, ovvero un’associazione tra la funzione e l’ambito nel quale è stata dichiarata, lo scope di cui abbiamo parlato prima.
Tornando al nostro codice, la closure che si è creata permette ai tre setTimeout di accedere alla stessa variabile message, che al momento dell’esecuzione del console.log è già arrivata alla posizione 3 e risulta quindi undefined.
Possiamo risolvere questo problema con una IIFE anonima

In questo caso il setTimeout è nello scope della funzione immediatamente invocata, quindi la variabile message non è più condivisa con le altre due chiamate.
Lo stesso risultato possiamo ottenerlo in ES6 dichiarando la variabile i come let

La variabile così dichiarata con let crea appunto una nuova closure ad ogni giro, proprio come nell’esempio precedente.
Ma andiamo avanti con un altro esempio dalla documentazione Mozilla, nel quale è utilizzata una closure per creare un contatore.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Emulating_private_methods_with_closures


La variabile privateCounter e la funzione changeValue, non sono visibili all’esterno della funzione MakeCounter, come sappiamo infatti sono all’interno dello scope di funzione, ma abbiamo reso disponibili con return all’esterno della funzione i metodi increment, decrement e getValue.
Queste tre funzioni appartengono allo stesso scope, quindi possono accedere a privateCounter e changeValue.
Assegnando come valore a delle nuove variabili la function expression MakeCounter(), ogni nuova variabile creerà una sua closure, conserverà un proprio valore di privateCounter e potrà chiamare i metodi increment, decrement e getValue.
Le closure possono quindi essere sfruttate anche per creare dei metodi privati, emulando linguaggi come java e php.
Se facciamo un console.log di counter1 otteniamo

counter1 è un oggetto e può accedere solo ai metodi resi da noi disponibili con return — increment, decrement e getValue — e alla variabile privateCounter.
Fonti:
https://www.packtpub.com/application-development/advanced-javascript
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
https://codingjam.it/di-non-sapere-javascript-scope-e-closures/
https://medium.com/@sbakkila/javascript-es-6-let-and-the-dreaded-temporal-dead-zone-85b89314d168
https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/