Skip to content
Skip to content
Menu
Info Cafe
Info Cafe

Una semplice guida per aiutarvi a capire le chiusure in JavaScript

By admin on Gennaio 20, 2021

Le chiusure in JavaScript sono uno di quei concetti che molti fanno fatica a capire. Nel seguente articolo, spiegherò in termini chiari cos’è una chiusura, e porterò il punto a casa usando semplici esempi di codice.

Una chiusura è una caratteristica in JavaScript in cui una funzione interna ha accesso alle variabili della funzione esterna (che racchiude) – una catena di scope.

La chiusura ha tre catene di scope:

  • ha accesso al proprio scope – le variabili definite tra le sue parentesi graffe
  • ha accesso alle variabili della funzione esterna
  • ha accesso alle variabili globali

Per i non iniziati, questa definizione potrebbe sembrare solo un sacco di gergo!

Ma cos’è veramente una chiusura?

Guardiamo un semplice esempio di chiusura in JavaScript:

function outer() { var b = 10;
function inner() {
var a = 20;
console.log(a+b);
}
return inner;
}

Qui abbiamo due funzioni:

  • una funzione esterna outer che ha una variabile b, e restituisce la inner funzione
  • una funzione interna inner che ha la sua variabile chiamata a, e accede ad una variabile outer variabile b, all’interno del suo corpo di funzione

Lo scopo della variabile b è limitato alla funzione outer, e lo scopo della variabile a è limitato alla funzione inner.

Invochiamo ora la funzione outer() e memorizziamo il risultato della funzione outer() in una variabile X. Invochiamo quindi la funzione outer() una seconda volta e memorizziamola nella variabile Y.

Vediamo passo dopo passo cosa succede quando la funzione outer() viene invocata per la prima volta:

  1. La variabile b viene creata, il suo ambito è limitato alla funzione outer() e il suo valore viene impostato a 10.
  2. La prossima linea è una dichiarazione di funzione, quindi niente da eseguire.
  3. Nell’ultima riga, return inner cerca una variabile chiamata inner, trova che questa variabile inner è in realtà una funzione, e quindi restituisce l’intero corpo della funzione inner.
  4. Il contenuto restituito dalla dichiarazione di ritorno è memorizzato in X.
    Quindi, X memorizzerà quanto segue:
    function inner() {
    var a=20;
    console.log(a+b);
    }
  5. La funzione outer() termina l’esecuzione, e tutte le variabili nello scope di outer() ora non esistono più.

Questa ultima parte è importante da capire. Una volta che una funzione completa la sua esecuzione, tutte le variabili che sono state definite all’interno dello scope della funzione cessano di esistere.

La durata di una variabile definita all’interno di una funzione è la durata dell’esecuzione della funzione.

Questo significa che in console.log(a+b), la variabile b esiste solo durante l’esecuzione della funzione outer(). Una volta che la funzione outer ha terminato l’esecuzione, la variabile b non esiste più.

Quando la funzione viene eseguita la seconda volta, le variabili della funzione vengono create di nuovo, e vivono solo fino a quando la funzione termina l’esecuzione.

Quindi, quando outer() viene invocato la seconda volta:

  1. viene creata una nuova variabile b, il suo ambito è limitato alla funzione outer(), e il suo valore viene impostato a 10.
  2. La linea successiva è una dichiarazione di funzione, quindi niente da eseguire.
  3. return inner restituisce l’intero corpo della funzione inner.
  4. Il contenuto restituito dalla dichiarazione di ritorno è memorizzato in Y.
  5. La funzione outer() termina l’esecuzione, e tutte le variabili nello scope di outer() ora non esistono più.

Il punto importante qui è che quando la funzione outer() viene invocata per la seconda volta, la variabile b viene creata nuovamente. Inoltre, quando la funzione outer() finisce di essere eseguita la seconda volta, questa nuova variabile b cessa di esistere.

Questo è il punto più importante da realizzare. Le variabili all’interno delle funzioni esistono solo quando la funzione è in esecuzione, e cessano di esistere una volta che la funzione completa l’esecuzione.

Ora, torniamo al nostro esempio di codice e guardiamo X e Y. Poiché la funzione outer() in esecuzione restituisce una funzione, le variabili X e Y sono funzioni.

Questo può essere facilmente verificato aggiungendo quanto segue al codice JavaScript:

console.log(typeof(X)); //X is of type function
console.log(typeof(Y)); //Y is of type function

Siccome le variabili X e Y sono funzioni, possiamo eseguirle. In JavaScript, una funzione può essere eseguita aggiungendo () dopo il nome della funzione, come X() e Y().

Quando eseguiamo X() e Y(), stiamo essenzialmente eseguendo la funzione inner .

Esaminiamo passo dopo passo cosa succede quando X() viene eseguito per la prima volta:

  1. Variabile a viene creata, e il suo valore viene impostato a 20.
  2. JavaScript ora cerca di eseguire a + b. Qui è dove le cose si fanno interessanti. JavaScript sa che a esiste poiché lo ha appena creato. Tuttavia, la variabile b non esiste più. Poiché b fa parte della funzione esterna, b esisterebbe solo mentre la funzione outer() è in esecuzione. Poiché la funzione outer() ha terminato l’esecuzione molto prima che noi invocassimo X(), tutte le variabili nell’ambito della funzione outer cessano di esistere, e quindi la variabile b non esiste più.

Come gestisce JavaScript questo?

Chiusure

La funzione inner può accedere alle variabili della funzione racchiusa grazie alle chiusure in JavaScript. In altre parole, la funzione inner conserva la catena di scope della funzione di chiusura nel momento in cui la funzione di chiusura è stata eseguita, e quindi può accedere alle variabili della funzione di chiusura.

Nel nostro esempio, la funzione inner aveva conservato il valore di b=10 quando la funzione outer() è stata eseguita, e continua a conservarlo (chiusura).

Ora si riferisce alla sua catena di scope e nota che ha il valore della variabile b all’interno della sua catena di scope, poiché aveva racchiuso il valore di b all’interno di una chiusura nel punto in cui la funzione outer era stata eseguita.

Quindi, JavaScript conosce a=20 e b=10, e può calcolare a+b.

Puoi verificarlo aggiungendo la seguente linea di codice all’esempio sopra:

Apri l’elemento Inspect in Google Chrome e vai alla Console. Puoi espandere l’elemento per vedere effettivamente l’elemento Closure (mostrato nella terzultima riga sotto). Notate che il valore di b=10 è conservato nel Closure anche dopo che la funzione outer() completa la sua esecuzione.

La variabile b=10 è conservata nella Closure, Closures in Javascript

Ripercorriamo ora la definizione di chiusura che abbiamo visto all’inizio e vediamo se ora ha più senso.

Quindi la funzione interna ha tre catene di scope:

  • accesso al proprio scope – variabile a
  • accesso alle variabili della funzione outer – variabile b, che ha racchiuso
  • accesso a qualsiasi variabile globale che può essere definita

Chiusure in azione

Per portare a casa il punto delle chiusure, aumentiamo l’esempio aggiungendo tre righe di codice:

Quando si esegue questo codice, si vedrà il seguente output nel console.log:

a=20 b=10
a=20 b=11
a=20 b=12
a=20 b=10

Esaminiamo questo codice passo dopo passo per vedere cosa succede esattamente e per vedere le chiusure in azione!

var X = outer(); // outer() invoked the first time

La funzione outer() viene invocata la prima volta. I seguenti passi hanno luogo:

  1. Variabile b viene creata, ed è impostata su 10
    Variabile c viene creata, e impostata su 100
    Chiamiamo questo b(first_time) e c(first_time) per nostro riferimento.
  2. La funzione inner viene restituita e assegnata a X
    A questo punto, la variabile b è racchiusa nella catena di scope della funzione inner come chiusura con b=10, poiché inner utilizza la variabile b.
  3. La funzione outer completa l’esecuzione e tutte le sue variabili cessano di esistere. La variabile c non esiste più, anche se la variabile b esiste come chiusura dentro inner.
var Y= outer(); // outer() invoked the second time
  1. La variabile b viene creata nuovamente ed è impostata su 10
    La variabile c viene creata nuovamente.
    Nota che anche se outer() è stato eseguito una volta prima che le variabili b e c cessassero di esistere, una volta che la funzione ha completato l’esecuzione vengono create come variabili nuove.
    Chiamiamo queste b(second_time) e c(second_time) per nostro riferimento.
  2. La funzione inner viene restituita e assegnata a Y
    A questo punto la variabile b è racchiusa nella catena di scope della funzione inner come chiusura con b(second_time)=10, poiché inner usa la variabile b.
  3. La funzione outer completa l’esecuzione, e tutte le sue variabili cessano di esistere.
    La variabile c(second_time) non esiste più, anche se la variabile b(second_time) esiste come chiusura dentro inner.

Ora vediamo cosa succede quando vengono eseguite le seguenti linee di codice:

X(); // X() invoked the first time
X(); // X() invoked the second time
X(); // X() invoked the third timeY(); // Y() invoked the first time

Quando X() viene invocato per la prima volta,

  1. viene creata la variabile a, e impostata su 20
  2. il valore di a=20, il valore di b è quello della chiusura. b(first_time), quindi b=10
  3. le variabili a e b sono incrementate da 1
  4. X() completa l’esecuzione e tutte le sue variabili interne – variabile a – cessano di esistere.
    Tuttavia, b(first_time) è stato conservato come chiusura, quindi b(first_time) continua ad esistere.

Quando X() viene invocato la seconda volta,

  1. la variabile a viene creata nuovamente, e impostata su 20
    Qualsiasi valore precedente della variabile a non esiste più, poiché ha cessato di esistere quando X() ha completato l’esecuzione la prima volta.
  2. il valore di a=20
    il valore di b è preso dal valore di chiusura – b(first_time)
    Nota anche che abbiamo incrementato il valore di b di 1 dalla precedente esecuzione, quindi b=11
  3. le variabili a e b sono aumentate di 1 di nuovo
  4. X() completa l’esecuzione e tutte le sue variabili interne – variabile a – cessano di esistere
    Tuttavia, b(first_time) è conservato in quanto la chiusura continua ad esistere.

Quando X() viene invocato la terza volta,

  1. la variabile a viene creata nuovamente, e impostata su 20
    Qualsiasi valore precedente della variabile a non esiste più, poiché ha cessato di esistere quando X() ha completato l’esecuzione la prima volta.
  2. il valore di a=20, il valore di b è dal valore di chiusura – b(first_time)
    Nota anche che avevamo incrementato il valore di b di 1 nella precedente esecuzione, quindi b=12
  3. le variabili a e b sono incrementate da 1 di nuovo
  4. X() completa l’esecuzione, e tutte le sue variabili interne – variabile a – cessano di esistere
    Tuttavia, b(first_time) viene conservato in quanto la chiusura continua ad esistere

Quando Y() viene invocato per la prima volta,

  1. la variabile a viene creata nuovamente e impostata su 20
  2. il valore di a=20, il valore di b è dal valore di chiusura – b(second_time), quindi b=10
  3. le variabili a e b sono incrementate di 1
  4. Y() completa l’esecuzione, e tutte le sue variabili interne – variabile a – cessano di esistere
    Tuttavia, b(second_time) è stato conservato come chiusura, quindi b(second_time) continua ad esistere.

Riservazioni conclusive

Le chiusure sono uno di quei concetti sottili in JavaScript che sono difficili da afferrare all’inizio. Ma una volta che le hai capite, ti rendi conto che le cose non avrebbero potuto andare diversamente.

Spero che queste spiegazioni passo dopo passo ti abbiano aiutato a capire davvero il concetto di chiusura in JavaScript!

Altri articoli:

  • Una guida rapida alle funzioni “autoinvocanti” in Javascript
  • Comprendere lo scope di funzione vs. lo scope di blocco in Javascript
  • Come usare le Promesse in JavaScript
  • Come costruire una semplice animazione Sprite in JavaScript

Navigazione articoli

Aric Almirola, Smithfield estende il contratto con lo Stewart-Haas Racing
5 motivi per cui dovreste comprare un Honda Ruckus

Lascia un commento Annulla risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Articoli recenti

  • Firebush (Italiano)
  • Previsione dei tassi CD per il 2021: I tassi rimarranno probabilmente bassi, ma potrebbero aumentare nel corso dell’anno
  • Come strutturare la documentazione del sistema di gestione della qualità
  • Dolore pelvico cronico e prostatite: sintomi, diagnosi e trattamento
  • Mixed Berry Crisp (Italiano)
  • Ricetta budino al cioccolato basso -carb
  • Giochi e attività salutari per i bambini | UIC Online Informatics
  • Wheat Ales (American) (Italiano)
  • I benefici dell’allattamento al seno dopo un anno
  • È sicuro buttare i fondi di caffè nel lavandino | Atomic Plumbing

Meta

  • Accedi
  • Feed dei contenuti
  • Feed dei commenti
  • WordPress.org

Archivi

  • Marzo 2021
  • Febbraio 2021
  • Gennaio 2021
  • Dicembre 2020
  • DeutschDeutsch
  • NederlandsNederlands
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • PolskiPolski
  • 日本語日本語
©2021 Info Cafe | WordPress Theme by SuperbThemes.com