WEB-d Développement Web

PHP, SQL, HTML5, CSS3, Javascript, Mootools, Référencement, SEO, CMS, e-commerce, Apache, Linux, Ubuntu, ...

Javascript, Mootools et les closures

Une propriétés très puissante de Javascript, lorsqu'on sait l'utiliser, est les support des closures. Une closure est une variable qui contient la définition d'une fonction, plus la liste des variables à laquelle cette fonction peut accéder. C'est un concept de programmation proche, mais différent, des "anonymous functions" aussi appelées "lambda-functions".

Dans l'exemple ci-dessous, la closure "f" a accès aux variables globales "a" et "b":


<script type="text/javascript">
  var a = "Hello";
  var b = "World!";

  var f = function() {
    alert(a + " " + b);
  }
  
  f(); // Affiche "Hello World!"
</script>

Il faut cependant bien garder en mémoire que ce qui est sauvé dans la closure est la liste des variables, pas leur valeur. La valeur de la variable est calculée au moment de l'appel de la fonction. L'exemple suivant, par exemple, affiche "World!":


<script type="text/javascript">
  var a = "Hello";
  
  var f1 = function() {
    alert(a);
  }

  a = "World!";
  f1(); // Affiche "World!"
</script>

Cette particularité peut avoir des effets surprenants, surtout à l'intérieur d'une boucle:


<script type="text/javascript">
    var my_functions = new Array();;

    for (var i=0; i<3; i++) {
        my_functions[i] = function() {
            alert(i);
        }
    }

    my_functions[0]();
    my_functions[1]();
    my_functions[2]();
</script>

L'exemple ci-dessus n'affiche PAS "1", "2", "3" comme on pourrait s'y attendre, mais bien "3", "3, "3". Comme la valeur de "i" est calculée au moment où on appelle la fonction, et comme cet appel a lieu après la fin de la boucle "for", la valeur de "i" est donc "3".

Heureusement, il existe quand même des techniques pour obtenir l'effet désiré. Dans le cas du framework mootoos, il s'agit de la fonction "pass(variable)":


<script type="text/javascript" src="mootools-core-1.3.2-full-compat-yc">
</script>

<script type="text/javascript">
  var my_other_functions = new Array();

  for (var i=0; i<3; i++) {
    my_other_functions[i] = function() {
      alert(arguments[0]); // la VALEUR de i est stockée dans arguments[0]
    }.pass(i);
  }

  my_other_functions[0](); // Affiche "0"
  my_other_functions[1](); // Affiche "1"
  my_other_functions[2](); // Affiche "2"
</script>

Au moment où on utilise fonction.pass(variable), la VALEUR de cette variable est stockée dans arguments[0], et peut donc être utilisée. L'exemple ci-dessous affiche donc "1", "2" et "3".

La documentation complète de la fonction bind peut naturellement être trouvée sur le site de Mootools.

Articles similaires