Visit Mozilla.org

Le principe de fermeture en JavaScript:Utilisation des fermetures

Un article de MDC.

Sommaire

[modifier] Exemple 1 : setTimeout avec des références de fonction et paramètres

(NDT : Beaucoup de libertés ont été prises dans "la traduction" de cette partie par rapport à l'original afin d'en simplifier au maximum sa compréhension)

Une utilisation fréquente du principe de « fermeture » est de fournir des paramètres pour l'exécution d'une fonction avant l'exécution de celle-ci. Par exemple, quand une fonction doit être utilisé par la méthode setTimout (méthode JavaScript implémenté sur la quasi-totalité des navigateurs acceptant le Javascript).

La méthode setTimeout programme l'exécution d'une fonction (ou d'une chaîne de caractère représentant du code Javascript à exécuter). Cette fonction est indiquée en premier paramètre. Elle s’exécute après un délai exprimé en millisecondes (paramètre indiqué en tant que deuxième argument). Le problème de cette méthode est qu’à l’exécution de cette fameuse fonction, il n’y a forcément le contexte désiré. Si un bout de code utilise le setTimeout, il appelle cette méthode en passant une référence à une fonction (objet Function) et l'intervalle, mais une référence à un objet de fonction ne peut pas fournir des paramètres pour l'exécution programmée de cette fonction. C'est-à-dire, si on créé un objet

 function Parole() {
   this.texte = "Bonjour !" ;
 }

Avec une méthode parle :

 Parole.prototype.parle = function() {
   alert("Je dis : " + this.texte) ;
 }

On désire la faire exécuter dans 10 secondes. On serait tenté d’écrire :

 var maParole = new Parole();
 setTimeout(maParole.parle,10000) ;

Et bien on obtient au bout de 10 seconde une alerte avec un jolie message « Je dis : undefined » !

Par contre, après avoir relus cette présentation sur le principe de fermeture on serait tenté d’écrire quelque chose du genre :

 var maParole = new Parole();
 function executeParole(o){
   return function(){o.parle()};
 }
 setTimeout(executeParole(maParole),10000);

Et bien là, ça marchera, vous obtiendrez le message « Je dis : Bonjour ! ».

Explication de la première tentative, quand, au bout de 10 secondes le setTimeout exécute la fonction parle(), l’argument this ne correspond pas à l’objet lui-même, mais l’objet window (auquel est justement attaché par défaut la méthode setTimeout) !

Il est également possible, avec ce principe d’exécuter une fonction avec passage de paramètres :

 function changerStyleBoite(styleDiv, prop, valeur){
   return (function(){
     /* cette fonction interne sera exécutée par le setTimeout.
        Lors de l’exécution, il pourra lire et exécuter en conséquence
        les paramètres qui avaient été passé auparavant dans la fonction
        externe */
       styleDiv[prop] = valeur;
   });
 }
 
 
 // prenons le style d’un objet
 var elemStyle = document.getElementById("boiteMessage").style;
 
 /* Appelle de la fonction retournant la référence à la fonction créée
    dans ce contexte d’exécution en passant les paramètres que la fonction
    interne utilisera. Cette référence est assignée à une variable locale
 */
 
 var refFonction = changerStyleBoite(elemStyle, "display", "none");
 
 // appelle de la reference à la fonction interne
 setTimeout(refFonction, 5000);
 // dans 5 secondes, l’élément « boiteMessage » va disparaître ! :-)


[modifier] Exemple 2 : Association des fonctions aux méthodes d'exemple d'objet

[modifier] Exemple 3 : Encapsulation de la fonctionnalité relative

[modifier] D'autres exemples

< Fermetures | Fermetures accidentelles >