di: Marco Solazzi 08 Novembre 2010
Chiunque abbia sviluppato una piccola applicazione o una semplice interattività in JavaScript si sarà imbattuto almeno un volta in un metodo che prevedesse una funzione di callback. Strutture di questo tipo si incontrano molto spesso utilizzando librerie come jQuery:
$('a').click(function () {
//qui il codice della callback
});
Molti sviluppatori non trovano alcun problema nell'utilizzare questo pattern di programmazione nel loro codice e molto spesso la causa principale di tale comportamento è la poca importanza attribuita alla progettazione di applicazioni JavaScript e l'utilizzo del linguaggio come surrogato di Flash o panacea alle limitazioni del DOM.
In effetti, sebbene il codice in questione sia del tutto legittimo, esso introduce delle limitazioni architetturali che precludono la modularità e scalabilità dell'applicazione.
La più pesante conseguenza di tutto ciò è che spesso ci si trova a riscrivere intere porzioni di codice per assecondare un'unica modifica dell'applicazione.
Le limitazioni nell'uso di callback derivano principalmente dal fatto che troppo spesso vi si associano funzioni anonime, una caratteristica potente ma pericolosa del linguaggio JavaScript:
el.onclick = function () {
//questa è una funzione anonima
};
var miaFunzione = function () {
// anche questa è una funzione anonima
};
Queste funzioni non sono identificabili in nessun modo da altre parti dell'applicazione e quindi servono un unico scopo e molto spesso si accompagnano a codice duplicato:
el.onclick = function () {
var box = document.getElementById('box');
box.style.color = '#F00';
};
el2.onclick = function () {
// codice duplicato
var box = document.getElementById('box');
box.style.color = '#F00';
};
Un primo passo per ottimizzare il codice precedente è quello di instanziare una funzione assegnandole un nome:
function cambiaColore () {
var box = document.getElementById('box');
box.style.color = '#F00';
}
el.onclick = cambiaColore;
el2.onclick = cambiaColore;
Si capisce subito che non solo si diminuisce il peso del codice, ma si rende tutta l'applicazione più facilmente aggiornabile.
Un altro vantaggio non indifferente è che sarà più facile fare riferimento alla funzione di callback in fase di debug.
Il più vistoso effetto collaterale di questo approccio è che comporta la definizione di molti oggetti globali, con il rischio che altri script possano sovrascrivere le funzioni definite precedentemente.
Per ovviare a questo problema si può utilizzare una funzione self-executing attraverso la quale contenere le funzioni in un contesto (scope) privato:
(function () {
function cambiaColore () {
var box = document.getElementById('box');
box.style.color = '#F00';
}
function altraFunzione () {
//codice
}
el.onclick = cambiaColore;
el2.onclick = altraFunzione;
})();
oppure usare un oggetto come namespace generico:
var mieFunzioni = {
cambiaColore : function () {
var box = document.getElementById('box');
box.style.color = '#F00';
},
altraFunzione : function () {
//codice
}
};
el.onclick = mieFunzioni.cambiaColore;
el2.onclick = mieFunzioni.altraFunzione;
In quest'ultimo caso il vantaggio è che le funzioni definite come metodi dell'oggetto mieFunzioni sono raggiungibili dal contesto globale e quindi riutilizzabili in altre parti dell'applicazione.
Guida Node.jsIl framework che permette di per usare V8, l'interprete JavaScript... |
Canvas, guida ai frameworkCanvas, tra gli elementi di HTML5 è forse quello di maggior impatto.... |
Guida jQuery UICreare siti ricchi e dinamici con jQuery UI, il progetto ufficiale... |
Ogni martedì, direttamente nella tua e-mail: guide, articoli, script, novità e approfondimenti tecnici su JavaScript.
Iscriviti alla newsletter
|
|
Corso Webmaster base18 Giugno 2012 a Milano |
|
|
Corso Google AdWords Base25 Giugno 2012 a Milano |
|
|
Corso JQuery e Ajax per Webmaster03 Luglio 2012 a Milano |
|
|
Corso Google AdWords Base05 Giugno 2012 a Roma |
|
|
Corso Webmaster base11 Giugno 2012 a Roma |