par
naholyr » 20 oct. 2006, 21:52
Le problème c'est que "this.display()" ca n'existe pas dans le corps d'exécution de setInterval().
Une méthode simple (et la plus propre que j'ai trouvée) est de globaliser l'objet, et de faire appeler la variable gloable par setInterval(). Je m'explique (dans tous les cas d'implémentation qui vont suivre, l'utilisation est
var obj=new MaClass(); obj.start();) :
function MaClasse() {
// initialisation de mon objet
this.compteur = 1;
this.start = function() {
setInterval("this.incremente()", 1000);
}
this.incremente = function() {
this.compteur++;
alert(this.compteur);
}
}
Ceci ne va bien sur pas fonctionner.
L'idée, c'est d'ajouter une variable globale qui vaut tout simplement "this" :
function MaClasse() {
// initialisation de mon objet
this.compteur = 1;
// creation d'un nom global
this.nomGlobal = "objetGlobal";
// globalisation de l'objet
window[this.nomGlobal] = this;
this.start = function() {
setInterval("window." + this.nomGlobal + ".incremente()", 1000);
}
this.incremente = function() {
this.compteur++;
alert(this.compteur);
}
}
Et voilà ça marche

(note que pour un code maxi-portable, on pourrait aussi bien utiliser MaClasse en lieu et place de window, on crée alors des attributs de classe à la volée au lieu de créer des variables globales)
Afin d'éviter les effets de bord lorsque plusieurs objets sont instanciés, on va créer un nouveau nom global unique a chaque création d'objet :
var prefixeGlobal = "__objet__";
var uniqid = 0;
do {
this.nomGlobal = prefixeGlobale + (uniqid++);
} while (typeof window[this.nomGlobal] != "undefined");
Voici donc la méthode que j'utilise quand je le fais "from scratch".
Le plus propre restant d'utiliser une librairie tres bien fichue, j'ai nommé prototype.js, voici comment on réecrirait tout ca, sans user de l'horrible "globalisation", grâce à l'incommensurablement maginifiquement bien pensé "bind()" (et pourtant si simple, il suffisait d'y penser et de bien connaître la mecanique interne de Javascript bien sûr) :
function MaClasse() {
// initialisation de mon objet
this.compteur = 1;
this.start = function() {
setInterval(this.incremente.bind(this), 1000);
}
this.incremente = function() {
this.compteur++;
alert(this.compteur);
}
}
Et voici comment on l'écrirait en "esprit prototype.js"
var MaClasse = Class.create();
MaClasse.prototype = {
initialize : function() {
this.compteur = 1;
},
start : function() {
this.timer = new PeriodicalExecuter(this.incremente.bind(this), 1);
},
incremente : function() {
this.compteur ++;
alert(this.compteur);
}
});
Le problème c'est que "this.display()" ca n'existe pas dans le corps d'exécution de setInterval().
Une méthode simple (et la plus propre que j'ai trouvée) est de globaliser l'objet, et de faire appeler la variable gloable par setInterval(). Je m'explique (dans tous les cas d'implémentation qui vont suivre, l'utilisation est [b]var obj=new MaClass(); obj.start();[/b]) :
[php]function MaClasse() {
// initialisation de mon objet
this.compteur = 1;
this.start = function() {
setInterval("this.incremente()", 1000);
}
this.incremente = function() {
this.compteur++;
alert(this.compteur);
}
}[/php]Ceci ne va bien sur pas fonctionner.
L'idée, c'est d'ajouter une variable globale qui vaut tout simplement "this" :
[php]function MaClasse() {
// initialisation de mon objet
this.compteur = 1;
// creation d'un nom global
this.nomGlobal = "objetGlobal";
// globalisation de l'objet
window[this.nomGlobal] = this;
this.start = function() {
setInterval("window." + this.nomGlobal + ".incremente()", 1000);
}
this.incremente = function() {
this.compteur++;
alert(this.compteur);
}
}[/php]Et voilà ça marche :) (note que pour un code maxi-portable, on pourrait aussi bien utiliser MaClasse en lieu et place de window, on crée alors des attributs de classe à la volée au lieu de créer des variables globales)
Afin d'éviter les effets de bord lorsque plusieurs objets sont instanciés, on va créer un nouveau nom global unique a chaque création d'objet :[php]var prefixeGlobal = "__objet__";
var uniqid = 0;
do {
this.nomGlobal = prefixeGlobale + (uniqid++);
} while (typeof window[this.nomGlobal] != "undefined");[/php]
Voici donc la méthode que j'utilise quand je le fais "from scratch".
Le plus propre restant d'utiliser une librairie tres bien fichue, j'ai nommé prototype.js, voici comment on réecrirait tout ca, sans user de l'horrible "globalisation", grâce à l'incommensurablement maginifiquement bien pensé "bind()" (et pourtant si simple, il suffisait d'y penser et de bien connaître la mecanique interne de Javascript bien sûr) :[php]function MaClasse() {
// initialisation de mon objet
this.compteur = 1;
this.start = function() {
setInterval(this.incremente.bind(this), 1000);
}
this.incremente = function() {
this.compteur++;
alert(this.compteur);
}
}[/php]
Et voici comment on l'écrirait en "esprit prototype.js"[php]var MaClasse = Class.create();
MaClasse.prototype = {
initialize : function() {
this.compteur = 1;
},
start : function() {
this.timer = new PeriodicalExecuter(this.incremente.bind(this), 1);
},
incremente : function() {
this.compteur ++;
alert(this.compteur);
}
});[/php]