Patterns de fonctions en Javascript

Dans ce dernier article de notre série consacrée aux fonctions en Javascript, examinons quelques patterns indispensables à une utilisation de base des fonctions.

Fonction de rappel

Une fonction de rappel (callback) consiste simplement en une évaluation en puissance d’une fonction. Généralement, il s’agit du passage d’une fonction à une autre pour une évaluation future de celle-ci. Nous utilisons par exemple une callback de manière systématique lorsque nous associons une fonction à un évènement.

Pour le fun, voyons comment ce code aurait pu être écrit en PHP 5.4, où l’absence d’IIFE nous oblige à recourir à une variable statique. La syntaxe de PHP nous permet toutefois de typer la fonction de rappel, et garantit ainsi une plus grande sûreté de programmation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function click(callable $callback=null){
    static $callbacks = array();
    if($callback){
        $callbacks[] = $callback;
    }else{
        foreach($callbacks as $callback){
            $callback();
        }
    }
}

//définition d'une fonction de callback
function foo(){ echo 2; }

//passage de callback
click(function(){ echo 1; }); //mise en file d'une première fonction
click('foo'); //mise en file d'une seconde fonction
click(); //affiche 1 puis 2

Fonction d’ordre supérieur

Les fonctions d’ordre supérieur (High-order function) permettent de recevoir une fonction en argument et de retourner une fonction comme résultat. Elles permettent notamment de générer de manière dynamique une fonction avec un comportement et un contexte qui lui sont propres: on parle aussi de curryfication (currying).

Toujours pour le fun, nous voyons qu’en PHP, la syntaxe nécessite d’utiliser use() pour passer les arguments à la fonction retournée qui n’est normalement pas perméable aux variables externes. La syntaxe de PHP nécessite donc d’être plus explicite. On peut regretter toutefois qu’il faille passer par une fonction variable $odd, et perdre ainsi en concision.

1
2
3
4
5
6
7
8
9
10
11
12
function not(callable $callback){
    return function() use($callback){
        return !call_user_func_array($callback, func_get_args());
    };
}

function even($value){
    return $value%2===0;
}

$odd = not('even');
var_dump($odd(1)); //affiche boolean true

Fermeture

Une fermeture, plus connue sous le nom originel et moins artificiel de closure, est une fonction qui conserve une référence de variables statiques propres. La valeur des variables contenues dans la fonction est déterminée indépendamment lors de chaque invocation.

Pour se faire, il est nécessaire de passer par une fonction contenante qui encapsule la portée des variables utilisées par la closure. La valeur de ces variables n’est connue que par la closure retournée, chacune d’entre elles ayant des références de variables indépendantes. Ces variables sont statiques dans la mesure où elles conservent leurs valeurs entre chaque appel de la closure.

Et juste pour le fun, voici l’équivalent en PHP, où la closure est obligatoirement anonyme et le passage de la variable d’incrémentation se fait obligatoirement par référence, puisque, contrairement à Javascript, il ne s’agit pas de la même variable. A nouveau, la syntaxe de PHP nécessite donc d’être plus rigoureux.

1
2
3
4
5
6
7
8
9
10
11
12
13
function getClosure(){
    $i = 0;
    return function() use(&$i){
        return ++$i;
    };
}

$incrementA = getClosure();
$incrementB = getClosure();

var_dump($incrementA()); //affiche int 1
var_dump($incrementA()); //affiche int 2
var_dump($incrementB()); //affiche int 1

Conclusion

Bien qu’assez simple à première vue, ce petit tour des fonctions en Javascript nous a néanmoins permis de bien cerner leur utilisation et leurs subtilités.

On comprend ainsi facilement des patterns de base comme les closure, les callback, ou les high-level function.

2 réflexions au sujet de « Patterns de fonctions en Javascript »

  1. Ping : Les closure en PHP | The Dark Side Of The Web

  2. Ping : Les fonctions en Javascript

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>