[Javascript] spiegazione della closure

Discussione in 'Javascript' iniziata da figlio1, 13 Febbraio 2018.

  1. figlio1

    figlio1 Nuovo Utente

    Registrato:
    13 Febbraio 2018
    Messaggi:
    3
    Mi Piace Ricevuti:
    0
    Punteggio:
    1
    Salve ragazzi , sto studiando javascript e mi sono imbattuto in questo codice :
    Codice:
    var saluto = "Buongiorno";
    var visualizzaSaluti;
    
    function saluta(persone) {
        
        var nomeCognome;
        var saluti = [];
        
        for (var i in persone) {
            nomeCognome = persone.nome + " " + persone.cognome;
            
            saluti.push(function() {
                console.log(saluto + " " + nomeCognome);
            });
        }
        return saluti;
    }
    
    visualizzaSaluti = saluta([{nome: "Mario", cognome: "Rossi"},
                               {nome: "Marco", cognome: "Neri"}]);
    
    for (var i in visualizzaSaluti) {
        visualizzaSaluti();
    }
    Non riesco a capire come mai viene restituito all'array saluti l'ultimo oggetto 2 volte , dove ho preso il codice dice che centra con la variabile nomeCognome la quale ha l'ultimo elemento dell'array persona....me lo spiegate? dovrebbe centrare col closure ma non l'ho capito
     
    Ultima modifica di un moderatore: 13 Febbraio 2018
  2. Max 1

    Max 1 Super Moderatore Membro dello Staff SUPER MOD MOD

    Registrato:
    29 Febbraio 2012
    Messaggi:
    2.840
    Mi Piace Ricevuti:
    220
    Punteggio:
    63
    Sesso:
    Maschio
    Ciao @figlio1
    Da regolamento del forum, come tutti noi sei tenuto ad usare il tag code.gif quando posti del codice, oppure la funzione codice dalla barra degli strumenti
    box inserisci 2.png.JPG
    Inoltre ti prego di leggere attentamente il regolamento generale del forum e quello di sezione dove posti
    Grazie
    Per questa volta te lo sistemo io ma mi raccomando per il futuro
     
  3. figlio1

    figlio1 Nuovo Utente

    Registrato:
    13 Febbraio 2018
    Messaggi:
    3
    Mi Piace Ricevuti:
    0
    Punteggio:
    1
    ok , lo farò
     
  4. WmbertSea

    WmbertSea Utente Attivo

    Registrato:
    28 Novembre 2014
    Messaggi:
    113
    Mi Piace Ricevuti:
    9
    Punteggio:
    18
    Ciao, premetto che eseguendo quello script salta fuori questo errore in console:
    Codice:
    TypeError: visualizzaSaluti is not a function
    che chiaramente è dovuto al fatto che nell'ultimo ciclo stai cercando di trattare quella variabile come una funzione, cosa che non è ma piuttosto si tratta di un array i cui elementi sono, loro, delle funzioni. Presumo quindi che ci manchi l'indice , per cui dovrebbe essere visualizzaSaluti(); così come per la variabile persone nel ciclo dentro la funzione saluta(), che dovrebbe essere persone.nome e persone.cognome.

    Sì, si tratta di una conseguenza dovuta alla closure (vedi definizione di Chiusura).

    Riporto qui una definizione presa da un altro sito in cui forse è spiegato in maniera più abbordabile:
    (Fonte: http://codingjam.it/di-non-sapere-javascript-scope-e-closures/)

    Ti direi che non è così semplice da spiegare perché comunque si devono avere chiari anche altri concetti, primo fra tutti il concetto di scope. Chiaramente queste nozioni, relativamente all'esempio che hai riportato qui, sono spiegate anche nella guida in cui hai trovato l'esempio stesso (che presumo tu abbia letto), per cui posso giusto darti un ulteriore commento con parole diverse ma sta poi a te sforzarti di capire.

    In sostanza tu hai la funzione principale saluta() al cui interno stai definendo un array saluti e i suoi elementi, i quali non sono altro che delle funzioni (che poi andrai a richiamare dall'esterno della funzione principale:
    Gli elementi sono quindi definiti in questo modo:
    Codice:
    saluti.push(function() {
        console.log(saluto + " " + nomeCognome);
    });
    Al loro interno (cioè dentro quel function(){}) stai usando (in particolare) la variabile nomeCognome che non è definita localmente dentro questa stessa function, ma è invece definita e valorizzata dentro il contesto (scope) della funzione principale saluta().

    Cosa succede quindi? Tu hai lanciato una prima volta saluta() per valorizzare l'array visualizzaSaluti (che conterrà gli elementi/funzioni):
    Codice:
    visualizzaSaluti = saluta([{nome: "Mario", cognome: "Rossi"},
                               {nome: "Marco", cognome: "Neri"}]);
    Successivamente stai richiamando queste funzioni in questo modo (chiaramente aggiungo l'indice mancante):
    Codice:
    for (var i in visualizzaSaluti) {
        visualizzaSaluti[i]();
    }
    Sarà quindi eseguita questa funzione (più volte, nel tuo caso 2, in base al numero di elementi definiti):
    Codice:
    function() {
        console.log(saluto + " " + nomeCognome);
    }
    dove la variabile nomeCognome era stata definita nello scope della funzione principale e ovviamente il suo valore non è altro che l'ultimo valore che gli è stato attribuito dopo che è stato eseguito il ciclo for (quello dentro la funzione principale).

    Quindi, dal momento che tu stai richiamando, dall'esterno della funzione saluta(), queste altre funzioni che erano definite al suo interno, viene "ricordato" il valore delle variabili relativamente al contesto della stessa funzione saluta(); quindi il valore di nomeCognome è esattamente quello che gli è restato assegnato per ultimo dopo l'esecuzione del ciclo (dentro la funzione) e al termine dell'esecuzione della stessa funzione saluta().

    Come è spiegato su quella guida, una soluzione a questo problema è l'uso di una IIFE , cioè una funzione che si auto-esegue, così da potergli passare come parametro il valore della variabile nomeCognome, in modo da restare "memorizzato" nello scope di quest'ultima funzione e non di quella principale.

    Spero di aver chiarito qualcosa.
    Buon proseguimento nello studio.
     
Sto caricando...

Condividi questa Pagina