Le clousure in JavaScript

Le chiusure rappresentano una tecnica di programmazione che consente di far ricordare alle funzioni il contesto in cui sono state create anche dopo la loro esecuzione

Quando in JavaScript si parla di clousure si intendono un insieme delle particolari funzioni che “ricordano” il contesto in cui sono state create. Prima di approfondire il discorso, ricordiamo che una funzione interna ha la capacità di accedere ai dati della funzione esterna che la contiene. Ad esempio:

    var myVar = 1;
    function myFunction() {
        console.log(myVar); // => 1
    }
    myFunction();

I dati e le funzioni di una funzione interna non sono accessibili al di fuori di essa. Queste proprietà vengono create quando la funzione è invocata e vengono cancellate quando la sua esecuzione termina. Una caratteristica importante delle clousure è che consentono di far sopravvivere il local scope di una funzione anche dopo la “morte” della funzione. Ogni qualvolta che JavaScript esegue una funzione viene allocato un riferimento alla funzione e un altro oggetto di tipo scope, quest’ultimo in genere viene rilasciato alla fine dell’esecuzione della funzione a meno che non ci sia nessun altro oggetto che punta ad esso. Una clousure combina una funzione con il suo ambiente di esecuzione.

Ecco un esempio di clousure:

    function makeNames(myFirstName) {
        return function(mySecondName) {
            return myFirstName + ' and ' + mySecondName;
        };
    }

    var myNames1 = makeNames("Alex");
    var myNames2 = makeNames("Robert");

    console.log(myNames1("Alex2")); // <= Alex and Alex2     console.log(myNames2("Robert2")); // <= Robert and Robert2

Nell’esempio appena mostrato è stata definita una funzione makeNames() al cui interno viene unito il primo nome inserito ad un secondo nome. La funzione viene utilizzata due volte, a questo punto è lecito pensare che la funzione makeNames() avrà come parametro myName l’ultimo valore passato… ciò però non è vero, quando si vanno ad utilizzare le funzioni myNames1 e myNames2 aggiungendo i secondi nomi, le funzioni ricordano le variabili locali al momento della loro creazione e i nomi vengono correttamente uniti come desiderato. Il motivo di tutto questo è dato dal fatto che la funzione makeNames() restituisce una funzione, le funzioni ritornate sono salvate nelle clousure myNames1 e myNames2 in quanto condividono lo stesso corpo della funzione ma hanno environments differenti. La funzione interna ha accesso ai dati (nell’esempio myFirstName) della funzione in cui è contenuta anche dopo che quest’ultima è stata ritornata.

Le clousure vengono utilizzate per aumentare la privacy degli oggetti simulando il concetto di metodo privato noto in molti linguaggi di programmazione. Consentono inoltre di nascondere i dettagli implementativi delle funzioni quando non è necessario e a mantenere il namespace globale in maniera efficiente.

    var myCounterFunction = (function() {
        var myPrivateNumber = 0;

        function myPrivateMethod(myNumber) {
            privateCounter += myNumber;
        }

        return {
            increment: function() {
                myPrivateMethod(1);
            },
            decrement: function() {
                myPrivateMethod(-1);
            },
            value: function() {
                return myPrivateNumber;
            }
        };
    })();

    console.log(myCounterFunction.value()); // => 0
    myCounterFunction.increment();
    console.log(myCounterFunction.value()); // => 1
    myCounterFunction.decrement();
    console.log(myCounterFunction.value()); // => 0

Nell’esempio appena definito è stata creata e subito eseguita una funzione anonima, assegnata alla variabile myFunction, al cui interno è stata creata un variabile privata ed un metodo privato non accessibili dall’esterno. Le uniche funzioni che possono essere utilizzate dall’esterno solo le funzioni “pubbliche” ritornate: increment, decrement e value. I dati interni alla funzione sono nascosti e non accessibili dall’esterno.

Una funzione anonima definita e subito invocata è detta anche Immediately-Invoked-Function-Expressions e consente di creareun nuovo scope consentendo quindi di emulare la “privacy” all’interno delle funzioni.

I principali vantaggi delle clousure è consentono di nascondere i dati degli oggetti e favorire il corretto incapsulamento degli oggetti. Le clousure devono essere utilizzati solo quando si vogliono trarre questi vantaggi, utilizzarle quando non è necessario fa solo diminuire la velocità dello script e aumentare il consumo di memoria.

Pubblicato in Front-end, JavaScript Taggato con: , , , ,

Lascia un commento

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

*