6.1 Concepto de closures
Los closures son uno de los conceptos más poderosos e importantes en JavaScript. Permiten a las funciones recordar su entorno léxico incluso después de haber sido ejecutadas. En esta lección, exploraremos el concepto de closures, sus características y proporcionaremos varios ejemplos de su uso.
Un closure en JavaScript es una combinación de una función y el entorno léxico en el que fue declarada. El closure permite que la función "recuerde" y acceda a las variables y otras funciones de su ámbito exterior incluso después de que la función externa haya sido ejecutada.
Propiedades principales de los closures:
- Entorno léxico: el contexto en el que se declara una función, incluyendo todas las variables disponibles al momento de la declaración.
- Preservación del contexto: una función con closure puede preservar el acceso a las variables del ámbito exterior incluso después de que se complete la ejecución de esta función externa.
6.2 Ejemplos de funcionamiento de los closures
Ejemplo 1: Closure simple
En este ejemplo, innerFunction() tiene acceso a la variable outerVariable de su ámbito exterior incluso después de que outerFunction() haya terminado de ejecutarse.
function outerFunction() {
let outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // Mostrará: I am from the outer function
Ejemplo 2: Contador usando closure
En este ejemplo, la función contador preserva el valor de la variable count y lo incrementa en cada llamada.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // Mostrará: 1
console.log(counter()); // Mostrará: 2
console.log(counter()); // Mostrará: 3
Ejemplo 3: Closure en un bucle
Los closures se utilizan a menudo para preservar los valores de las variables en los bucles.
En este ejemplo, cada función dentro del array arr "recuerda" el valor de la variable i en el momento de su creación gracias al ámbito de bloque de let:
function createArrayWithClosures() {
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
const closures = createArrayWithClosures();
closures[0](); // Mostrará: 0
closures[1](); // Mostrará: 1
closures[2](); // Mostrará: 2
6.3 Escenarios complejos de uso de closures
Ejemplo 1: Aplicación parcial de funciones
Los closures permiten crear funciones parcialmente aplicadas, manteniendo algunos argumentos fijos.
En este ejemplo, la función multiply() devuelve una función que multiplica el argumento b pasado a ella por el argumento fijo a.
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // Mostrará: 10
console.log(double(10)); // Mostrará: 20
Ejemplo 2: Ocultación de datos
Los closures pueden utilizarse para crear variables y métodos privados.
En este ejemplo, las variables _name y _age son privadas y solo son accesibles a través de los métodos del objeto:
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function() {
return _name;
},
getAge: function() {
return _age;
},
setName: function(newName) {
_name = newName;
},
setAge: function(newAge) {
_age = newAge;
}
};
}
const person = createPerson('John', 30);
console.log(person.getName()); // Mostrará: John
person.setName('Jane');
console.log(person.getName()); // Mostrará: Jane
console.log(person.getAge()); // Mostrará: 30
Ejemplo 3: Memoización
La memoización es una técnica de optimización en la que los resultados de una función se almacenan para evitar cálculos repetidos para los mismos datos de entrada.
En este ejemplo, la función memoize() utiliza closures para almacenar en caché los resultados calculados de la función fn():
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function slowFunction(num) {
console.log('Computing...');
return num * 2;
}
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // Mostrará: Computing... 10
console.log(memoizedFunction(5)); // Mostrará: 10 (resultado obtenido de la caché)
GO TO FULL VERSION