Un ejemplo implica un cierre, el otro no. Implementar cierres es un poco complicado, ya que las variables cerradas no funcionan como las variables normales. Esto es más obvio en un lenguaje de bajo nivel como C, pero usaré JavaScript para ilustrar esto.
Un cierre no solo consiste en una función, sino también en todas las variables sobre las que se cerró. Cuando queremos invocar esa función, también debemos proporcionar todas las variables cerradas. Podemos modelar un cierre por una función que recibe un objeto como primer argumento que representa estas variables cerradas 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
Tenga en cuenta que la convención de llamadas extrañas closure.apply(closure, ...realArgs)
esto requiere
El soporte de objetos integrado de JavaScript hace posible omitir el argumento explícito vars
, y nos permite usar this
en su lugar:
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
Esos ejemplos son equivalentes a este código que realmente usa cierres:
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
En este último ejemplo, el objeto solo se usa para agrupar las dos funciones devueltas; El enlace this
es irrelevante. Todos los detalles para hacer posibles los cierres (pasar datos ocultos a la función real, cambiar todos los accesos a las variables de cierre y buscar en esos datos ocultos) están a cargo del idioma.
Pero los cierres de llamadas implican la sobrecarga de pasar esos datos adicionales, y la ejecución de un cierre implica la sobrecarga de las búsquedas en esos datos adicionales, empeorada por la mala ubicación de la memoria caché y, por lo general, una falta de referencia de puntero cuando se compara con las variables comunes, por lo que es No sorprende que una solución que no se basa en cierres funcione mejor. Especialmente, ya que todo lo que le permite hacer el cierre es un par de operaciones aritméticas extremadamente baratas, que incluso se pueden plegar constantemente durante el análisis.