Um exemplo envolve um fechamento, o outro não. A implementação de fechamentos é meio complicada, pois as variáveis fechadas não funcionam como variáveis normais. Isso é mais óbvio em uma linguagem de baixo nível como C, mas usarei JavaScript para ilustrar isso.
Um fechamento não consiste apenas de uma função, mas também de todas as variáveis que ele encerrou. Quando queremos chamar essa função, também precisamos fornecer todas as variáveis de fechamento. Podemos modelar um fechamento por uma função que recebe um objeto como primeiro argumento que representa essas variáveis fechadas sobre:
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
Observe a convenção de chamada estranha que closure.apply(closure, ...realArgs)
isso exige
O suporte a objetos embutidos do JavaScript permite omitir o vars
argumento explícito e, em this
vez disso , vamos usar :
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
Esses exemplos são equivalentes a esse código, na verdade, usando closures:
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
Neste último exemplo, o objeto é usado apenas para agrupar as duas funções retornadas; a this
ligação é irrelevante. Todos os detalhes de tornar possíveis os fechamentos - passando dados ocultos para a função real, alterando todos os acessos às variáveis de fechamento para pesquisas nesses dados ocultos - são resolvidos pelo idioma.
Mas chamar encerramentos envolve a sobrecarga de passar esses dados extras, e executar um encerramento envolve a sobrecarga de pesquisas nesses dados extras - agravadas pela má localização do cache e, geralmente, por uma desreferência de ponteiro quando comparadas às variáveis comuns -, portanto, não é surpreendente que uma solução que não depende de fechamentos tem melhor desempenho. Especialmente porque tudo o que seu fechamento lhe permite fazer são algumas operações aritméticas extremamente baratas, que podem até ser dobradas constantemente durante a análise.