• Sobre mí
  • Proyectos
  • Contacto
  • Blog

Apasionado por el desarrollo web y el diseño de interfaces intuitivas.

Cada error es un paso. Cada línea, un aprendizaje.

📍   Salou, Tarragona, España ✉️   [email protected] 📞   +34 641932611

Curriculum

Ver mi curriculum completo

Mapa del sitio

  • Inicio
  • Blog
  • Proyectos
  • Sobre mi
  • Mi misión
  • Sitemap

Contácto

  • Página de contácto
  • LinkedIn
  • GitHub

2026 Frankuxui - Todos los derechos reservados

  • Términos y condiciones
  • Política de privacidad
  • Política de cookies
Foto de unsplash creada por Avatar del usuario Matteo Catanese
Foto de unsplash creada por Avatar del usuario Matteo Catanese
  • JavaScript

Articulo publicado el 23 de julio de 2026

Por Frank Esteban Isdray Junco

Closures en JavaScript: Explicación Práctica

Domina los cierres y escribe código más limpio y poderoso

Los closures son uno de los conceptos más poderosos y, al mismo tiempo, más confusos de JavaScript. Si has trabajado con JavaScript por un tiempo, probablemente ya los has usado sin siquiera darte cuenta. En esta guía, desglosaré qué son, cómo funcionan y, lo más importante, cuándo y cómo usarlos en tus proyectos.

¿Qué es un Closure?

Un closure es una función que tiene acceso a variables de su función padre, incluso después de que esa función ha terminado de ejecutarse. Esto ocurre porque en JavaScript, las funciones crean su propio scope, y las variables de ese scope persisten mientras exista una referencia a la función interna.

Veamos un ejemplo simple:

javascript
function saludar(nombre) {
  const mensaje = `Hola, ${nombre}`;

  return function () {
    console.log(mensaje);
  };
}

const saludo = saludar("Ana");
saludo(); // Output: "Hola, Ana"

En este ejemplo, la función interna tiene acceso a nombre y mensaje, que son variables del scope de la función externa. Aunque saludar() ya ha terminado de ejecutarse, la función interna aún puede acceder a esas variables. Eso es un closure.

Cómo Funcionan los Closures

Para entender realmente cómo funcionan los closures, es importante comprender qué sucede con el scope en JavaScript:

El Scope Chain

Cada función en JavaScript crea su propio scope. Cuando buscas una variable, JavaScript la busca en:

  1. El scope local de la función
  2. El scope de la función padre
  3. El scope global

Esta cadena de búsqueda se llama el scope chain. Los closures aprovechan esto manteniendo viva la referencia al scope externo.

javascript
const global = "global";

function externa() {
  const externa_var = "externa";

  function interna() {
    const interna_var = "interna";

    console.log(interna_var); // "interna"
    console.log(externa_var); // "externa"
    console.log(global); // "global"
  }

  return interna;
}

const closure = externa();
closure(); // Todos los console.log funcionan correctamente

Persisten en la Memoria

Lo importante es que las variables en el scope de la función padre no se descartan cuando la función termina. Mientras exista una referencia a la función interna, esas variables permanecerán en memoria.

javascript
function crearContador() {
  let contador = 0; // Esta variable persiste

  return function () {
    contador++;
    return contador;
  };
}

const miContador = crearContador();
console.log(miContador()); // 1
console.log(miContador()); // 2
console.log(miContador()); // 3

Casos de Uso Prácticos

Encapsulamiento de Datos

Los closures son perfectos para mantener datos privados que no pueden ser accedidos directamente desde el exterior:

Crear Variables Privadas

javascript
function crearCuenta(saldoInicial) {
  let saldo = saldoInicial; // Variable privada

  return {
    depositar(cantidad) {
      saldo += cantidad;
      return saldo;
    },
    retirar(cantidad) {
      if (cantidad <= saldo) {
        saldo -= cantidad;
        return saldo;
      }
      return "Saldo insuficiente";
    },
    obtenerSaldo() {
      return saldo;
    }
  };
}

const miCuenta = crearCuenta(1000);
console.log(miCuenta.depositar(500)); // 1500
console.log(miCuenta.obtenerSaldo()); // 1500
console.log(miCuenta.saldo); // undefined (privada)

Function Factory

javascript
function crearOperacion(operador) {
  return function (a, b) {
    switch (operador) {
      case "+":
        return a + b;
      case "-":
        return a - b;
      case "*":
        return a * b;
      default:
        return null;
    }
  };
}

const sumar = crearOperacion("+");
const restar = crearOperacion("-");

console.log(sumar(10, 5)); // 15
console.log(restar(10, 5)); // 5

Callbacks y Event Listeners

Los closures son esenciales para mantener contexto en callbacks:

javascript
function crearBotonMultiple(id, titulo) {
  const boton = document.getElementById(id);
  let clickCount = 0;

  boton.addEventListener("click", function () {
    clickCount++;
    console.log(`${titulo} ha sido clickeado ${clickCount} veces`);
  });
}

crearBotonMultiple("btn1", "Botón Principal");
crearBotonMultiple("btn2", "Botón Secundario");

Cada listener mantiene su propio clickCount gracias a los closures.

Debouncing y Throttling

javascript
function debounce(fn, delay) {
  let timeoutId; // Variable privada que persiste

  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), delay);
  };
}

const buscar = debounce(function (query) {
  console.log("Buscando:", query);
}, 500);

// Cada vez que se escribe, se cancela el timeout anterior

Configuración de Módulos

javascript
const miModulo = (function () {
  const apiKey = "clave-secreta"; // Privada
  let cachedData = null; // Privada

  return {
    obtenerDatos(url) {
      if (cachedData) return cachedData;
      // Usar apiKey internamente
      cachedData = fetch(`${url}?key=${apiKey}`);
      return cachedData;
    },
    limpiarCache() {
      cachedData = null;
    }
  };
})();

Cuándo Usar y Cuándo Evitar

Cuándo Usar Closures

Casos Ideales para Aplicar Closures
  • Necesitas crear variables privadas
  • Quieres mantener estado asociado a una función
  • Implementas patrones como factory functions o decorators
  • Necesitas callbacks que requieran contexto específico

Cuándo Evitar

  • El closure causa memoria leak (referencia infinita)
  • La lógica es tan compleja que un closure la hace difícil de entender
  • Existen alternativas más legibles (clases, módulos ES6)
javascript
// Evitar exceso de closures anidados
function nivel1() {
  return function nivel2() {
    return function nivel3() {
      return function nivel4() {
        // Demasiado complejo
      };
    };
  };
}

Performance y Consideraciones

Memory Leaks Potenciales

Los closures pueden causar memory leaks si no tienes cuidado:

javascript
// ❌ Problema: mantiene referencia a todo el DOM
function crearLlamador(elemento) {
  return function () {
    console.log(elemento.innerText); // elemento nunca se libera
  };
}

// ✅ Solución: extrae solo lo necesario
function crearLlamador(elemento) {
  const texto = elemento.innerText;
  return function () {
    console.log(texto);
  };
}

Closures vs Clases

En JavaScript moderno, a menudo tienes opciones:

javascript
// Con Closure
function crearPersona(nombre) {
  return {
    obtenerNombre() {
      return nombre;
    }
  };
}

// Con Clase
class Persona {
  constructor(nombre) {
    this.nombre = nombre;
  }

  obtenerNombre() {
    return this.nombre;
  }
}

Ambas funcionan, pero las clases suelen ser más legibles y debuggeables.

Conclusión

Los closures son una característica fundamental de JavaScript que te permite escribir código más modular, seguro y elegante. No son complicados una vez que entiendes la idea central: las funciones internas tienen acceso a las variables de sus funciones padre, y esas variables persisten mientras exista una referencia a la función interna.

Usa closures para encapsular datos, mantener estado privado y crear abstracciones poderosas. Pero siempre ten en mente la legibilidad de tu código y las alternativas modernas como las clases y los módulos ES6.

En este artículo

  1. ¿Qué es un Closure?
  2. Cómo Funcionan los Closures
  3. El Scope Chain
  4. Persisten en la Memoria
  5. Casos de Uso Prácticos
  6. Encapsulamiento de Datos
  7. Crear Variables Privadas
  8. Function Factory
  9. Callbacks y Event Listeners
  10. Debouncing y Throttling
  11. Configuración de Módulos
  12. Cuándo Usar y Cuándo Evitar
  13. Cuándo Usar Closures
  14. Cuándo Evitar
  15. Performance y Consideraciones
  16. Memory Leaks Potenciales
  17. Closures vs Clases
  18. Conclusión

Articulos relacionados

Estos articulos pueden interesarte si te gusto este articulo.

Imagen de unsplash creada por Peter Burdon
Imagen del articulo Fotografía de Unsplash
23 de julio de 2026
JavaScript

Debounce y Throttle: Controla la frecuencia de ejecución de funciones

Optimiza el rendimiento de tu aplicación limitando cuántas veces se ejecutan listeners de eventos y funciones costosas

Imagen de unsplash creada por Frans Ruiter
Imagen del articulo Fotografía de Unsplash
23 de julio de 2026
JavaScript

Event Delegation en JavaScript Vanilla: Optimiza tu DOM

Cómo reducir listeners y mejorar el rendimiento usando bubbling de eventos

Foto de unsplash creada por Avatar del usuario Mikolas Voborsky
Imagen del articulo Async/Await moderniza la forma en que manejamos operaciones asincrónicas en JavaScript
23 de julio de 2026
JavaScript

Async/Await y Promises en JavaScript

Domina la programación asíncrona desde cero