¿Qué es un closure y para qué sirve?
Ver respuesta — intenta responderla en voz alta primero
Un closure es una función que "recuerda" las variables del ámbito donde fue creada, incluso después de que ese ámbito haya terminado de ejecutarse. Sirve para mantener estado privado y para crear funciones configurables.
Cuando defines una función dentro de otra, la función interna conserva acceso a las variables de la externa. Aunque la función externa ya haya terminado, la interna sigue "recordando" esas variables. Esa combinación de función + variables recordadas se llama closure.
Es uno de los fundamentos de JavaScript. Se usa para:
- Mantener estado privado (variables que solo la función puede tocar).
- Crear funciones a partir de otras funciones (fábricas de funciones).
- Callbacks, manejadores de eventos, etc.
// Contador con estado privado gracias al closure
function crearContador() {
let cuenta = 0; // esta variable queda "encerrada"
return function () {
cuenta++;
return cuenta;
};
}
const contador = crearContador();
console.log(contador()); // 1
console.log(contador()); // 2
console.log(contador()); // 3
// "cuenta" no es accesible desde afuera: es privada
// Fábrica de funciones: cada una recuerda su propio "factor"
function multiplicarPor(factor) {
return function (numero) {
return numero * factor;
};
}
const duplicar = multiplicarPor(2);
const triplicar = multiplicarPor(3);
console.log(duplicar(5)); // 10
console.log(triplicar(5)); // 15
El clásico bug del bucle for con var:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Imprime 3, 3, 3 (no 0, 1, 2)
Con var, todas las funciones comparten la misma i, que termina siendo 3. La solución es usar let, que crea una nueva variable por iteración, y cada closure recuerda la suya.
"Un closure es una función que recuerda las variables del ámbito donde fue creada, incluso después de que ese ámbito haya terminado. Por ejemplo, si tengo una función que devuelve otra función, la función devuelta sigue teniendo acceso a las variables de la primera. Esto me permite mantener estado privado, como un contador cuya variable no se puede modificar desde afuera, o crear funciones configurables como un
multiplicarPor(2)."
Crea una función crearSaludo(saludo) que devuelva otra función que reciba un nombre y devuelva el saludo completo. Ejemplo: crearSaludo("Hola")("Mike") debería devolver "Hola, Mike".
Ver solución
function crearSaludo(saludo) {
return function (nombre) {
return `${saludo}, ${nombre}`;
};
}
console.log(crearSaludo("Hola")("Mike")); // "Hola, Mike"