Un exemple implique une fermeture, l'autre non. La mise en œuvre des fermetures est un peu délicate, car les variables fermées ne fonctionnent pas comme les variables normales. C'est plus évident dans un langage de bas niveau comme C, mais je vais utiliser JavaScript pour illustrer cela.
Une fermeture ne consiste pas seulement en une fonction, mais aussi en toutes les variables qu'elle a fermées. Lorsque nous voulons invoquer cette fonction, nous devons également fournir toutes les variables fermées. Nous pouvons modéliser une fermeture par une fonction qui reçoit un objet comme premier argument qui représente ces variables fermées:
function add(vars, y) {
vars.x += y;
}
function getSum(vars) {
return vars.x;
}
function makeAdder(x) {
return { x: x, add: add, getSum: getSum };
}
var adder = makeAdder(40);
adder.add(adder, 2);
console.log(adder.getSum(adder)); //=> 42
Notez la convention d'appel maladroite que closure.apply(closure, ...realArgs)
cela nécessite
La prise en charge des objets intégrés de JavaScript permet d'omettre l' vars
argument explicite et nous permet d'utiliser à la this
place:
function add(y) {
this.x += y;
}
function getSum() {
return this.x;
}
function makeAdder(x) {
return { x: x, add: add, getSum: getSum };
}
var adder = makeAdder(40);
adder.add(2);
console.log(adder.getSum()); //=> 42
Ces exemples sont équivalents à ce code utilisant des fermetures:
function makeAdder(x) {
return {
add: function (y) { x += y },
getSum: function () { return x },
};
}
var adder = makeAdder(40);
adder.add(2);
console.log(adder.getSum()); //=> 42
Dans ce dernier exemple, l'objet n'est utilisé que pour regrouper les deux fonctions retournées; lethis
liaison n'est pas pertinente. Tous les détails pour rendre les fermetures possibles - passer des données cachées à la fonction réelle, changer tous les accès aux variables de fermeture en recherches dans ces données cachées - sont pris en charge par le langage.
Mais appeler des fermetures implique la surcharge de la transmission de ces données supplémentaires, et l'exécution d'une fermeture implique la surcharge de recherches dans ces données supplémentaires - aggravées par une mauvaise localité de cache et généralement une déréférence de pointeur par rapport aux variables ordinaires - de sorte qu'il n'est pas surprenant que une solution qui ne repose pas sur des fermetures fonctionne mieux. D'autant plus que tout ce que votre fermeture vous permet d'économiser est quelques opérations arithmétiques extrêmement bon marché, qui pourraient même être pliées en permanence pendant l'analyse.