Salve a tutti, sono nuovo nel forum e desidero anzitutto fare i complimenti ad andr3a per questa pillola, semplicemente eccezionale!
Tuttavia vorrei chiarimi alcuni dubbi, riguardo il namespacing e il fantomatico this.
1) Namespacing
Come si legge nel link postato da kentaromiura (http://www.dustindiaz.com/namespace-your-javascript/), l'approccio tramite il namespacing offre indubbi vantaggi tra cui l'assenza di eventuali "collisioni" ed in generale un codice - a mio avviso - più "pulito".
Tuttavia mi sembra di capire che il namespace non sia propriamente una definizione di classe (perdonatemi se vi sembra una cosa ovvia, è la prima volta che ho a che fare coi namespace): questo comporta che un simile approccio sia più utile a definire una sorta di libreria di variabili e funzioni globali, più che ad una effettiva programmazione a oggetti... o sbaglio?
Provo a spiegarmi meglio: stando agli ultimi esempi riportati nella pagina linkata qui sopra, è come se alla fine disponessi di una unica istanza di un oggetto che fa capo al nome di MyNamespace, ma senza la possibilità di creare nuove istanze.
Se le cose stanno così, trovo che la cosa sia alquanto limitante... qualcuno ha per caso sperimentato uno stile di programmazione basato su namespacing che consenta di costruire delle classi vere e proprie?
2) This
A seguito di svariati esperimenti, mi sembra che il contesto venga perso abbastanza facilmente, ad esempio quando si usano funzioni callback:
codice:
my_class = function () {
this.message='ok';
this.metodo_a = function () {
setTimeout(this.metodo_b, 1);
}
this.metodo_b = function () {
setTimeout(this.metodo_c, 1);
}
this.metodo_c = function () {
alert(this.message);
}
}
ciccio = new my_class();
ciccio.metodo_c(); //alert('ok');
ciccio.metodo_b(); //alert('undefined') --> metodo_c non trova this.message ;
ciccio.metodo_a(); //Errore --> metodo_b non trova this.metodo_c ;
Per cui ad esempio se volessi creare una animazione, l'unico modo che sono riuscito a trovare per risolvere il problema è:
codice:
my_animation = function () {
...
this.step = function (oClass) {
var next_step = function () {
oClass.step(oClass);
}
// fai qualcosa
this.timer = setTimeout(next_step, 1000);
}
...
this.start = function () {
this.step(this);
}
...
this.stop = function () {
if (this.timer) {
clearTimeout(this.timer);
}
}
}
...che è poi quanto precisato da andr3a:
Per ovviare a questa serie di problematiche, è sufficiente ricordarsi di inviare il referente stesso alle funzioni interne che lo richiedono.
(a proposito andr3a, nei tuoi esempi usi 'self' dove io uso 'oClass'... self è sicuramente + intuitivo, ma siccome è utilizzato nel DOM... non fa confusione? posso usarlo senza problemi?)
Piccola nota al codice: perché definisco la funzione next_step? Semplice:
la sintassi di setTimeout è:
codice:
timer_id = setTimeout(callback_function, millisecondi[, param_1[, param2...]]);
ma per il "magico" Internet Explorer è:
codice:
timer_id = setTimeout(callback_function, millisecondi[, language]);
...quindi ho adottato questo semplice trucco.
Tuttavia questo codice mi sembra alquanto aggrovigliato... qualche idea per migliorarne leggibilità e/o efficienza?
Grazie e a presto,
gi_gio