CAP 04 · LEC 05·Funciones

Closures: funciones que recuerdan su entorno

Un closure es una función que mantiene acceso a las variables de su ámbito léxico incluso después de que ese ámbito haya finalizado. Es el mecanismo detrás de callbacks, módulos, memoización y React hooks.

● AVANZADO12 min lectura5 ejerciciospor Fernando Herrera · actualizado mayo de 2026
¿Encontraste un error o algo que mejorar?Editá esta lección en GitHub →

¿Qué es un closure?

Una función en JavaScript recuerda el entorno donde fue creada. Cuando retorna otra función desde adentro, la función interna tiene acceso a las variables de la externa — incluso después de que la función externa haya terminado.

function crearContador() { let cuenta = 0; // variable en el ámbito de crearContador return function() { cuenta++; return cuenta; }; } const contador = crearContador(); // crearContador() ya terminó, pero 'cuenta' sigue viva console.log(contador()); // 1 console.log(contador()); // 2 console.log(contador()); // 3 // Cada llamada a crearContador() crea un closure NUEVO const contador2 = crearContador(); console.log(contador2()); // 1 — independiente del primero
function crearContador(): () => number { let cuenta = 0; return () => { cuenta++; return cuenta; }; } const contador = crearContador(); // crearContador() ya terminó, pero 'cuenta' sigue viva console.log(contador()); // 1 console.log(contador()); // 2 console.log(contador()); // 3 // Cada llamada a crearContador() crea un closure NUEVO const contador2 = crearContador(); console.log(contador2()); // 1 — independiente del primero
Salida1 2 3

Casos de uso comunes

// 1. Encapsulación (estado privado) function crearCuenta(saldoInicial) { let saldo = saldoInicial; // privado — no accesible desde fuera return { depositar: (monto) => { saldo += monto; }, retirar: (monto) => { saldo -= monto; }, consultar: () => saldo, }; } const cuenta = crearCuenta(100); cuenta.depositar(50); cuenta.retirar(30); console.log(cuenta.consultar()); // 120 // console.log(cuenta.saldo); // undefined — privado // 2. Factory functions (creadores) function multiplicador(factor) { return (numero) => numero * factor; } const doble = multiplicador(2); const triple = multiplicador(3); console.log(doble(5)); // 10 console.log(triple(5)); // 15 // 3. Memoización function memoizar(fn) { const cache = new Map(); return function(...args) { const clave = JSON.stringify(args); if (cache.has(clave)) return cache.get(clave); const resultado = fn(...args); cache.set(clave, resultado); return resultado; }; } const fibMemo = memoizar(function fib(n) { if (n <= 1) return n; return fibMemo(n - 1) + fibMemo(n - 2); }); console.log(fibMemo(40)); // 102334155 (rápido)
// 1. Encapsulación (estado privado) function crearCuenta(saldoInicial: number) { let saldo = saldoInicial; return { depositar: (monto: number) => { saldo += monto; }, retirar: (monto: number) => { saldo -= monto; }, consultar: (): number => saldo, }; } const cuenta = crearCuenta(100); cuenta.depositar(50); cuenta.retirar(30); console.log(cuenta.consultar()); // 120 // 2. Factory functions (creadores) function multiplicador(factor: number) { return (numero: number): number => numero * factor; } const doble = multiplicador(2); const triple = multiplicador(3); console.log(doble(5)); // 10 console.log(triple(5)); // 15
Salida120 10 15

Ámbito léxico y la cadena de scope

const global = "global"; function externa() { const extVar = "externa"; function interna() { const intVar = "interna"; // Accede a su propio scope, al de externa, y al global console.log(intVar, extVar, global); } interna(); } externa(); // "interna" "externa" "global" // Problema clásico con var en loops (antes de ES6) // ❌ var comparte la misma variable en todos los closures for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); // 3 3 3 (no 0 1 2) } // ✅ let crea un nuevo binding por iteración for (let j = 0; j < 3; j++) { setTimeout(() => console.log(j), 0); // 0 1 2 }
React hooks y closures

Los hooks de React son closures. useEffect, useCallback y useMemo capturan variables del componente. Por eso el array de dependencias existe — le dice a React qué variables del closure podrían cambiar.

Practica