@Jarno
Scusa l'utente TrueLies se ti risponde in arabo. Parla a nuora perché suocera intenda, era rivolto a me. Ormai interviene nelle discussioni solo se sono intervenuto io. Figurati, è un onore per me. Ma non credo che faccia un gran servizio a questo forum.

@TrueLies
Atteggiamento da ragazzino di undici anni. Come al solito ti risponderò punto per punto.

Originariamente inviato da TrueLies
A parte i copia e incolla da mozilla
Vedo che continui a sprecare tempo a lanciare inutili strali contro il sottoscritto. Lascia stare, è una battaglia persa

si tratta di variazioni sulle cosiddette enclosures. In realtà, non hai molti motivi per utilizzare questo tipo di espressioni, o perlomeno non sono pensate per evitare l' "inquinamento" degli spazi globali (anche se puoi utilizzarle a tale scopo, ma ha poco senso: uno sviluppatore conosce il suo ambiente di produzione e sa quali variabili o strutture dati vi operano).
Sei sicuro? Esistono tanti tipi di sviluppatori, non esistono solo i webmaster. Esiste anche chi scrive script molto complessi con centinaia di variabili ma non per utilizzarli egli stesso, ma per renderli disponibili ai webmaster (script come jquery e similia). In quel caso lo sviluppatore ha il dovere di racchiudere il proprio codice in una closure se vuole che l'utente che usufruisce del suo script possa inserire con tranquillità anche altri script nella sua pagina.

Ad una variabile puoi assegnare come valore una funzione:
var foo=function(arg){alert(arg);}
ora, chiaramente:
foo('ciao'); chiama la funzione e lancia l'alert.

La sopravvivenza del valore passato all' argomento (nel nostro caso 'ciao') tuttavia non è sempre certa.
Che ci vuoi fare, è questione di fede.

Se ad esempio l'argomento di foo fosse una risposta ajax (interroghi il server con ajax, e la tua funzione rimane in ascolto della risposta del server) un sintassi del tipo
var foo=function(risposta){alert(risposta);}
non funzionerebbe: siccome il server risponde dopo un certo tempo (magari mezzo secondo, ma comunque NON subito, non istantaneamente), ma la funzione è eseguita subito, si smarrisce la possibilità di assegnare il valore che a 'risposta' darà il server: la funzione si esegue SUBITO ma il server fornirà il valore di 'risposta' PIU' TARDI.
Il fatto è che succede anche con istruzioni in campo libero dopo una qualsiasi richiesta asincrona, non c'entrano niente le funzioni, né lambda né dichiarate.

Una espressione invece del tipo:
var foo=function(risposta){function(){alert(risposta)} }
che incapsula una funzione dentro una funzione, consente la sopravvivenza del namespace (ed è questo il namespace che di solito si vuole preservare - quello asincrono non quello dell' oggetto window).

Siamo nell' ambito del currying e del lambda: sono trucchetti usati o per garantire la sopravvivenza degli argomenti di una funzione in un ambiente dove tale sopravvivenza non è certa, o per passare funzioni come argomenti di altre funzioni.

Non ti preoccupare del gran mal di testa: è uno di quegli argomenti che devi sfruttare così: archivi la sua esistenza, poi quando un giorno ti troverai innanzi alla necessità in un tuo codice di fare sopravvivere un argomento di funzione o di passare una funzione come argomento ad una altra e troverai delle difficoltà, ti ricorderai di questo argomento e sarà allora, applicandolo ai tuoi codici, che lo capirai meglio.
Temo di aver capito l'utilità che tu attribuisci alle closures e, ahimé, è uno degli usi più criticati che esistano. È il tipico uso simile al seguente:

codice:
link n. 1

link n. 2

link n. 3

link n. 4

link n. 5

link n. 6</p>
<script type="text/javascript">
	function restituisciAlert (nId) {
		return function() { alert("hai cliccato sul link numero" + nId); return false; };
	}

	var aLinks = document.links;
	for (var iLnkId = 0; iLnkId < aLinks.length; iLnkId++) {
		aLinks[iLnkId].onclick = restituisciAlert(iLnkId + 1);
	}
</script>
Il nostro caro amico così intento agli obiettivi pratici immagino che non si curi del fatto che verranno create tante closures per quanti sono i link della pagina. Immagino che volutamente ignori le tante soluzioni alternative che non generano closures, come l'uso di getUserData e setUserData, degli id o dell'operatore let:

Uso di getUserData e setUserData:

codice:
link n. 1

link n. 2

link n. 3

link n. 4

link n. 5

link n. 6</p>
<script type="application/javascript">
	function alclick () { alert("hai cliccato sul link numero" + this.getUserData("numero")); return false; }

	for (var iLnkId = 0, aLinks = document.links; iLnkId < aLinks.length; iLnkId++) {
		aLinks[iLnkId].setUserData("numero", iLnkId + 1, null);
		aLinks[iLnkId].onclick = alclick;
	}
</script>
Uso degli id:

codice:
link n. 1

link n. 2

link n. 3

link n. 4

link n. 5

link n. 6</p>
<script type="application/javascript">
	function alclick () { alert("hai cliccato sul link numero" + /\d+/.exec(this.id)); return false; }

	for (var iLnkId = 0, aLinks = document.links; iLnkId < aLinks.length; iLnkId++) {
		aLinks[iLnkId].id = "mioLink" + String(iLnkId + 1);
		aLinks[iLnkId].onclick = alclick;
	}
</script>
Uso dell'operatore let:

codice:
link n. 1

link n. 2

link n. 3

link n. 4

link n. 5

link n. 6</p>
<script type="application/javascript;version=1.7">
	var aLinks = document.links;
	for (var iLnkId = 0; iLnkId < aLinks.length; iLnkId++) {
		let nThisId = iLnkId + 1;
		aLinks[iLnkId].onclick = function () { alert("hai cliccato sul link numero" + nThisId); return false; };
	}
</script>
Quanto a capirlo completamente, no non accadrà: per quale motivo questo incapsulamento esita in questo tipo di comportamento infatti deriva solo dalla maniera in cui è stato progettato l'interprete javascript e non da alcuna virtù misteriosofica delle espressioni lambda che si autoimporrebbe a javascript: javascript si comporta a questo modo perchè degli essere umani lo hanno istruito a comportarsi in questo modo - è una convenzione, non una forza della natura che si rivela.
È dura non capire a fondo un linguaggio, eh?

Ah scusa, per completezza di discorso e per verificare come spesso si faccia uso di enclosures senza che ve ne sia alcun motivo reale (per questo sottolineavo che la funzioni in currying o lambda ha senso usarle quando serve, e non solo perchè lo si può: è inutile sparare ai canarini con i carri armati):

se tu hai una pagina con una query, che so:
nomepagina.php?yourVar=2&pippo=ciao it's good to see you

La struttura dati minimale:

var getVars={
'foo': function(){ var s=window.location.search.substring(1).split('&'); for(var i in s){this[s[i].substring(0, s[i].indexOf('='))]=unescape( s[i].substring(s[i].indexOf('=')+1) );} return this;}
};

alert(getVars.foo().pippo);
alert(getVars.foo().yourVar);

ti esegue quanto desiderato, cioè ottenere un oggetto dove siano raccolte come proprietà gli elementi della query, in maniera semplicissima e più leggibile. (meglio ancora sarebbe non mettere il return this e invocare una volta sola foo(), in maniera da non ripopolare, e poi invocatolo una volta sai che disponi delle proprietà: semplice e diretto allo scopo, e senza inquinare alcun namespace che non sia quello già impiegato di getVars).
A parte il fatto che il codice che ho postato io non genera closures (sei sicuro di aver capito a fondo cos'è una closure? guarda che non basta avere una funzione per avere una closure!) e a parte gli errori di approccio al problema in questione contenuti nella tua funzione, che senso ha scrivere un oggetto con una chiave contenente una funzione che popola l'oggetto medesimo? Non era molto più sensato scrivere la funzione fuori dall'oggetto?? Mi spieghi quante closures in meno genera la tua funzione?? La funzione che avevo postato non è minimale per il semplice fatto che è in grado di interpretare numeri come numeri, booleani come booleani, etc etc. Se vuoi puoi rendere minimale anche quella:

codice:
var oGetVars = new (function(sSearchStr) {
	if (sSearchStr.length > 1) {
		for (var iCouple, iCouplId = 0, aCouples = sSearchStr.substr(1).split("&"); iCouplId < aCouples.length; iCouplId++) { this[iCouple = aCouples[iCouplId].split("="), unescape(iCouple[0])] = iCouple.length > 1 ? unescape(iCouple[1]) : ""; }
	}
})(window.location.search);
Interessante poi l'uso dell'operatore in con gli array&hellip; Se esegui il codice seguente con un vecchio browser ti comparirà anche la chiave length nell'alert. Non è un caso che si tratti di una scrittura sconsigliata.

codice:
	var aAnimali = ["cane", "gatto", "topo"];
	var sPrint = "L'array contiene le seguenti chiavi:";
	for (var sChiave in aAnimali) {
		sPrint += "\n" + sChiave + ": " + aAnimali[sChiave];
	}
	alert(sPrint);
Poi puoi aggiungerci qualche dettaglio ma quello che mi preme sottolineare è che il fatto che tu veda su megasiti come Google o come Mozilla delle implementazioni barocche (il loro scopo di solito è meramente didattico: non ti suggeriscono che tu debba fare così, ma solo ti segnalano una prassi possibile: sta a te capire che l'intento didattico non coincide con l'incoraggiamento ad applicare la soluzione indiscriminatamente), non deve indurti a pensare che quelle implementazioni siano necessarie: come Feyerabend disse una volta, il fatto che sotto una soluzione inutile siano collezionate delle firme scientifiche autorevoli non rende la soluzione più utile ma la rende solo "una enciclica scientifica".
Definizione di barocco a parte, potrei essere d'accordo sull'aspetto didattico di siti come il Mozilla Developer Center. Il didatta della funzione in questione però è il sottoscritto, sono stato io a postarla, in seguito a una discussione nata proprio in questo forum.

Non perdere quindi il capo su quel che fa Google (che magari avrà i suoi motivi per fare le cose, ma il loro 'backstage' non ci è giustamente noto, o magari non li avrà): archivia il fatto che il currying e le espressioni lambda sono possibili, e poi usale quando ti accorgerai che davvero possono servirti e risolverti un problema, non iniziare ad usarle solo perchè si può o perchè rende il tuo codice più "cool" a vedersi
@Jarno
Non perdere tempo con Google o con il Mozilla Developer Center, ascolta il buon TrueLies

Originariamente inviato da TrueLiesO, almeno, io ti suggerisco di imparare a programmare così: in maniera funzionale, e non estetica, mettendo nella tua faretra le soluzioni che oggi non ti servono per quando ti accorgerai che ti servono.

Poi, beninteso, liberissimo di seguire altri approcci meno orientati all' obbiettivo pratico. Nulla in contrario.
Approcci meno orientati all'obiettivo pratico??? Meno male che c'è lui.

@Jarno
Scusaci, è che TrueLies non riesce proprio a farne a meno di mettersi in ridicolo.