esatto pietro, quello è uno dei tanti modi per sfruttare le cosiddette closures di JavaScript... andiamo avanti con l'approfondimento?
codice:
window.onload = function(){
for(var
bs = document.getElementsByTagName("input"),
i = 0;
i < bs.length;
i++
){
bs[i].onclick = (function(i){
// la i che arriva in questa funzione
// non c'entra niente con la i esterna
// ed avrà il giusto valore
// del momento e non l'ultimo assegnato
// dal ciclo for esterno
return function(){
// questa funzione può chiamare
// variabili nella closure esterna
// (quella con la nuova i)
// e fuori ancora fino alla window
// passando per l'onload ...
// quindi anche bs sarà raggiungibile
alert(++i);
// il primo input al primo onlcick
// mostrerà 1, il secondo 2 e via dicendo
};
})(i); // la i del for che alla fine sarà === bs.length
};
};
fin qui è tutto chiaro, bello e semplice ... ma se vogliamo preoccuparci anche della memoria utilizzata e delle performances dobbiamo valutare cosa accade in questo esempio: 2 funzioni nuove memorizzate per ogni input!
Anche se quella "esterna" viene utilizzata solo per racchiudere quella i, nell'esempio di pietro quella s, questa non potrà essere eliminata dal Garbage Collector finchè il nodo associato non verrà rimosso e cancellato (reso non riutilizzabile).
Sebbene il trucchetto sia comodo ed in questo caso di semplice gestione anche per i PC più datati, qualora le operazioni fossero molte di più, cosa che capita facilmente, sarebbe un sistema di difficile digestione e/o portabilità.
In questi casi è sempre consigliabile utilizzare lo scope dell'oggetto al fine di sfruttare e memorizzare una sola funzione piuttosto che N.
Per evitare infatti di ritrovarsi una variabile i ormai incrementata e con valore pari alla length degli input basta salvarla nel nodo occupando memoria per un'intero, memoria irrisoria se confrontata a quella necessaria per immagazzinare dozzine di funzioni alla volta più le variabili inviate a queste funzioni (la i nel mio esempio, la s in quello di pietro) che possono essere numerose.
Ecco quindi come ottimizzare il tutto ottenendo lo stesso risultato:
codice:
function onBSClick(){
alert(++this.i);
};
window.onload = function(){
for(var
bs = document.getElementsByTagName("input"),
i = 0;
i < bs.length;
i++
){
bs[i].i = i; // assegno questa i al nodo
bs[i].onclick = onBSClick; // assegno un riferimento alla funzione
// invece di usare 2 closures
// ogni nodo per fare sempre la stessa cosa
};
};
Questo ha poco a che fare con le closures ma in realtà è una conseguenza naturale per evitare bad practices di programmazione anche dove consentite, ovvero utilizzando miriade di closures non sempre indispensabili come in questo semplice esempio.