Pré-requis pour ce tutoriel

  • Un navigateur web (Mozilla Firefox, Google Chrome, Safari aux choix)
  • Un outil de développement (Coda, Dreamweaver, Aptana, Notepad++, etc.)
  • Des bases en programmation Javascript

Utilisation classique des fonctions setTimeout et setInterval

En Javascript, les méthodes setTimeout(callback, timer) et setInterval(callback, timer) sont utilisées pour appeler une portion de code de manière décalée dans le temps. Le code représenté par callback est appelé au bout de timer millisecondes écoulées après l’appel d’une de ces deux fonctions. La différence entre ces deux fonctions réside dans le fait que « setTimeout » n’appelle qu’une fois la portion de code, alors que « setInterval » appelle régulièrement la portion de code, toutes les timer millisecondes.

Voici comment ces deux fonctions s’utilisent :

function myFunction() {
    alert('Hello world !');
}
setTimeout('myFunction', 1000); // myFunction est appelée au bout de 1 seconde
setInterval('myFunction', 2000); // myFunction est appelée toutes les 2 secondes

Utilisation dans un contexte objet

Lorsque l’on développe en objet en Javascript, la donne change très sensiblement, ainsi si vous souhaitez utiliser les méthodes « setTimeout » ou « setInterval » vous aurez bien souvent tendance à vouloir écrire :

setTimeout('this.myMethod()', 1000);

Mais ce bout de code ne fera que générer un bug et n’appellera pas votre méthode. Pourquoi donc? Pour la simple et bonne raison que dans le modèle objet Javascript, toute méthode descend de l’objet « window« . Et à ce titre la méthode « setTimeout » descend également de cet objet. Lorsque vous effectuez un appel à une méthode, prenons par exemple la méthode « alert« , et bien si vous écrivez :

alert('Hi everybody');

Cela revient à écrire :

window.alert('Hi everybody');

De même si vous écrivez votre propre fonction :

function myFunction() {
    alert('myFunction called');
}

Et que vous l’appelez en faisant :

myFunction();

Cela revient à écrire :

window.myFunction();

Ainsi dans le cas qui nous intéresse ici, lorsque vous appelerez « myMethod« , le code s’executera dans l’espace de nommage de « setTimeout » et donc par extension de l’objet « window« . Javascript tentera d’appeler la méthode appertenant à l’objet « window » et comme celle-ci n’existe pas, cela provoquera une erreur.

La solution dans notre cas est d’utiliser une fonction anonyme. Le concept de fonction anonyme est très souvent utilisé en Javascript, il s’agit d’une fonction à laquelle aucun nom n’est donné et qui est bien souvent transmise en paramètre à une autre fonction. On retrouve souvent cette pratique dans les librairies Javascript du type jQuery, prototype, etc.

Puisqu’un bout de code est toujours plus parlant qu’un long discours, voici de quoi résumer ce que l’on vient de traiter ci-dessus :

function myMethod() {
    alert('window.myMethod() called');
}
 
var myObject = {
    myMethod: function() {
        alert('myObject.myMethod() called');
    },
 
    callDelayed: function() {
        setTimeout('this.myMethod()', 3000); // la méthode sera appelée au bout de 3 secondes
        setTimeout(function() { myObject.myMethod(); }, 1000); // la méthode se appelée au bout d'1 seconde
    }
};
 
myObject.callDelayed();

Le résultat de l’exécution de ce code sera :

myObject.myMethod() called
window.myMethod() called

Je vous conseille d’essayer cette portion de code. C’est fait ? Et voilà c’était pas si compliqué que ça :)

Bon mais alors maintenant vous allez me dire: « C’est bien beau tout ça, mais si j’ai plusieurs instances de mon objet comment je fais? Parce que dans ton code là on écrit en dur le nom de l’objet à qui appartient la méthode ». Et là je vous répondrais que vous êtes très perspicace ! J’y viens.

Utilisation dans le contexte d’un objet instanciable

Le principe de base à retenir ici est qu’il est nécessaire de préciser sur quel objet on appelle la méthode en question. Dans le cas où l’on dispose de plusieurs instances de l’objet, le code va différer quelque peu, dans la mesure où l’on ne pourra plus utiliser « myObject » sinon Javascript ne saura pas quelle méthode appeler. En Javascript pour construire un objet il suffit d’écrire une fonction portant le nom de la « classe » que vous souhaitez créer, puis de faire un « new » suivi du nom de la fonction. Voici dans le code qui va nous intéresser :

var myStdObject = function(name) {
    var oThis = this; // création d'une référence vers l'objet courant
    this.name = name;
 
    this.myMethod = function() {
        alert('myMethod() called on '+this.name);
    };
 
    this.callDelayed = function() {
        // utilisation de la référence vers l'objet
        setTimeout(function() { oThis.myMethod(); }, 2000);
    };
};
 
var myInstOne = new myStdObject('Instance 1');
var myInstTwo = new myStdObject('Instance 2');
 
myInstOne.callDelayed();
myInstTwo.callDelayed();

Le résultat de l’execution de ce script sera :

myMethod called on Instance 1
myMethod called on Instance 2

Pour conclure…

Et voilà le tour est joué ! Vous aurez sans doute remarqué que la syntaxe de mon objet est différente de précédemment. En effet dans le premier cas j’avais écrit un objet répondant au pattern Singleton (à savoir qu’il est instancié une et une seule fois dès lors que le script est exécuté). Dans le second cas j’ai écris un objet pouvant être réutilisé et instancié autant de fois que nécessaire. En Javascript la notation objet est, il faut l’avouer, un peu déroutante au début, ainsi pour développer un objet instaciable il suffit d’écrire une fonction qui s’avère être en réalité le constructeur de notre classe. Par la suite les membres de la classe s’écrivent en utilisant l’écriture avec le point « this.foobar« . Mais nous aurons l’occasion de revenir sur tout ça dans un prochain tuto ;)