[Javascript] spiegazione della closure

figlio1

Nuovo Utente
13 Feb 2018
3
0
1
21
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:

Max 1

Super Moderatore
Membro dello Staff
SUPER MOD
MOD
29 Feb 2012
4.402
338
83
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
 

WmbertSea

Utente Attivo
28 Nov 2014
208
33
28
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.

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
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:
Una “chiusura” (closure) è quello che una funzione è capace di ricordare del contesto (lexical scope) dalla quale proviene, anche se viene eseguita al di fuori di esso.
(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.
 
Discussioni simili
Autore Titolo Forum Risposte Data
L countdown multiplo javascript Javascript 1
S Problemi Javascript + Aruba Javascript 2
M Inviare un file su un server remoto con JavaScript Javascript 0
T a href="javascript:;" Javascript 0
F Creare elementi html con javascript Javascript 4
A pulsante di update campo mysql con javascript Javascript 2
8 Javascript - PDF Form Javascript 0
B javascript per problemi con pdf e Safari Javascript 0
N informazione javascript Programmazione 0
I Eecuzione di javascript in ciclo foreach php. PHP 7
P javascript:document.forms Javascript 7
S Consiglio esercizio Javascript Javascript 2
MarcoGrazia Aggiungere o rimuovere classi in javascript Javascript 1
P Passaggio id php a javascript PHP 6
E lettura da un Database con Javascript jQuery 2
V TRIS in javascript Javascript 1
IClaude Funzione Javascript Javascript 8
Alex_70 Javascript date color Javascript 3
F Convertire JavaScript per la compatibilità nei browser obsoleti Javascript 0
I Passare dei parametri in javascript PHP 0
Shyson Meglio Javascript o HTML? Javascript 4
M Chiamare pagina php da javascript Javascript 8
M Errore JavaScript per php [objeto HTMLParagraphElement] PHP 0
D Javascript per il download dei dati Javascript 0
grgfede Problema javascript con aruba Javascript 1
webmachine [PHP] [JAVASCRIPT] Form strano in HTML PHP PHP 1
W Modificare il Type di un Input box in javascript ovunque si trovi Javascript 0
I javascript come caricare una pagina sopra quella corrente in automatico Javascript 2
L [Javascript] Problema salvataggio dati in db Javascript 1
max1974 [Javascript] Grafico chartjs con dati da J.ajax Javascript 3
G Quiz Javascript Javascript 4
A [Javascript] Scrittura su più campi contemporaneamente Javascript 19
F classic asp popolare combo box javascript Presentati al Forum 1
claudio_lorenzo [Javascript] aiuto su jquery per calcolo altezze dom Javascript 1
F [Javascript] comando innerHTML non funziona Javascript 5
alexice51 proggrammi per scrivere in javascript? Javascript 3
max1974 [Javascript] Accordion aria-exspanded Javascript 0
D [Javascript] salvare immagine canvas - paypal Javascript 0
O [Javascript] Conflitto Jquery: forse... Javascript 0
M [Javascript] Canvas js css Javascript 1
M Programmazione web HTML, CSS e JavaScript Offerte e Richieste di Lavoro e/o Collaborazione 6
G [Javascript] Errore inserimento dati Backend Node.js e workbench Javascript 1
A Creare con Javascript un percorso all'interno di uno spazio Javascript 0
D [Javascript] inserire uno script in un file php Javascript 6
Monital [Javascript] inserire dati estratti dal db in html fisso Javascript 1
K [javascript] Tecnica per rilevare celle contenenti caratteri ricevute in dinamico Javascript 1
F [JavaScript] Ottenere il CSS dopo transform: scale() e transform-origin Javascript 0
S [Javascript] Problema costrutto if Javascript 0
I [Javascript] window.location.href porta alla nuova pagina e ritorna incomprensibilmente. Javascript 0
L [Javascript] input variabili di scrittura con canvas Javascript 2

Discussioni simili