Entender cómo una función puede recordar variables de su contexto original es una de las habilidades más valiosas que puedes desarrollar en JavaScript. Los closures son exactamente eso: funciones que retornan otras funciones y que mantienen acceso al scope en el que fueron creadas, incluso después de que ese contexto haya terminado de ejecutarse.
¿Qué es un closure y por qué es tan importante?
Un closure se produce cuando una función interna tiene acceso a las variables de su función externa. Esto ocurre porque JavaScript permite que las funciones "recuerden" el entorno léxico donde fueron definidas. No se trata solo de teoría: es un patrón que aparece constantemente en entrevistas técnicas y en código real de producción.
Para ilustrar este concepto, veamos un ejercicio que surgió en un code challenge durante una entrevista de trabajo [0:20]. La función BuildSum recibía un argumento, y más abajo se esperaba que funcionara de la siguiente manera:
javascript
const addFive = BuildSum(5);
console.log(addFive(5)); // 10
El reto consistía en completar la función para que esas dos líneas produjeran el resultado correcto.
¿Cómo se resuelve con un closure?
La solución es retornar otra función desde BuildSum [1:02]:
javascript
function BuildSum(a) {
return function(b) {
return a + b;
}
}
- Al ejecutar
BuildSum(5), el valor 5 se asigna al parámetro a.
- La función interna se guarda en la variable
addFive.
- Cuando llamamos
addFive(5), el parámetro b recibe 5 y se retorna la suma a + b, es decir, 10.
Lo fundamental aquí es que la segunda función no necesita declarar a porque ya está recordando el scope de la función externa [1:25]. Esa es la esencia del closure.
¿Cómo se ve con arrow functions?
Mediante un refactor con arrow functions, la misma lógica se simplifica enormemente [1:40]:
javascript
const BuildSum = a => b => a + b;
Esta línea hace exactamente lo mismo que la versión anterior. Si ya has trabajado con funciones como la función tag para generar etiquetas HTML en sesiones previas, este patrón te resultará familiar.
¿Cómo se relacionan los closures con function composition y currying?
Los closures no existen de forma aislada. Son la base sobre la que se construye function composition [2:05], un patrón que permite combinar funciones pequeñas para crear comportamientos más complejos. De hecho, si has generado etiquetas HTML componiendo funciones, ya has estado usando closures sin saberlo.
Además, los closures están estrechamente ligados al concepto de currying [2:15], que consiste en transformar una función que recibe múltiples argumentos en una secuencia de funciones que reciben un argumento a la vez. Ambos conceptos trabajan juntos para permitir la composición de funciones de manera limpia y reutilizable.
En resumen, dominar los closures te da tres ventajas concretas:
- Reutilización de lógica: puedes crear funciones parcialmente configuradas como
addFive.
- Encapsulamiento: las variables del scope externo permanecen protegidas.
- Composición: se vuelve natural construir funciones a partir de otras funciones.
Si este patrón todavía se siente abstracto, practica creando tus propias funciones que retornen funciones. Comparte en los comentarios qué otros usos le encuentras a los closures en tus proyectos.