NUCBA
22 de marzo de 2026
Frontend

Closures vs variables globales: cuándo usar cada una

Los closures no son magia. Te muestro cuándo realmente los necesitás y cuándo es mejor usar variables globales en JavaScript.

NUCBA

NUCBA

6 min de lectura

Closures vs variables globales: cuándo usar cada una

Los closures en JavaScript tienen fama de complicados. La realidad es que los usás todo el tiempo sin darte cuenta. El problema es que la mayoría de los tutoriales te explican con ejemplos de contadores que nunca vas a escribir en la vida real.

Te voy a mostrar cuándo los closures realmente te sirven, cuándo es mejor usar variables globales, y cómo decidir entre una y otra opción.

Qué son los closures (sin verso)

Un closure es cuando una función "recuerda" las variables del scope donde fue creada, incluso después de que ese scope ya no existe.

function crearContador() {
  let count = 0;
  
  return function() {
    count++;
    return count;
  };
}

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

La función interna todavía puede acceder a count aunque crearContador ya terminó de ejecutarse. Eso es un closure.

Casos reales donde los closures te salvan

Encapsular estado en componentes

Supongamos que tenés un modal que necesita controlar su propio estado:

function crearModal(selector) {
  const elemento = document.querySelector(selector);
  let estaAbierto = false;
  
  return {
    abrir() {
      if (!estaAbierto) {
        elemento.style.display = 'block';
        estaAbierto = true;
      }
    },
    cerrar() {
      if (estaAbierto) {
        elemento.style.display = 'none';
        estaAbierto = false;
      }
    },
    toggle() {
      estaAbierto ? this.cerrar() : this.abrir();
    }
  };
}

const modalUsuario = crearModal('#modal-usuario');
const modalConfirmacion = crearModal('#modal-confirmacion');

Cada modal tiene su propio estado estaAbierto que no puede ser modificado desde afuera. No hay forma de romperlo accidentalmente.

Configurar event listeners con datos específicos

Cuando tenés una lista de elementos y cada uno necesita comportarse diferente:

function configurarBotones(productos) {
  productos.forEach(producto => {
    const boton = document.querySelector(`#btn-${producto.id}`);
    
    boton.addEventListener('click', function() {
      // El closure "captura" el producto específico
      agregarAlCarrito(producto.id, producto.precio);
      mostrarNotificacion(`${producto.nombre} agregado al carrito`);
    });
  });
}

Sin closures tendrías que usar data- attributes o alguna otra solución más verbosa.

Crear funciones de configuración

Este patrón es muy común en librerías:

function crearValidador(reglas) {
  return function(valor) {
    for (let regla of reglas) {
      if (!regla.test(valor)) {
        return { valido: false, error: regla.mensaje };
      }
    }
    return { valido: true };
  };
}

const validarEmail = crearValidador([
  { test: v => v.includes('@'), mensaje: 'Debe contener @' },
  { test: v => v.length > 5, mensaje: 'Muy corto' }
]);

const validarPassword = crearValidador([
  { test: v => v.length >= 8, mensaje: 'Mínimo 8 caracteres' },
  { test: v => /\d/.test(v), mensaje: 'Debe tener números' }
]);

Cuándo usar variables globales en su lugar

Los closures no siempre son la respuesta. A veces una variable global es más simple y clara.

Estado de aplicación compartido

Si múltiples partes de tu app necesitan acceder al mismo dato:

// Mejor así
window.usuarioActual = null;
window.configuracion = { tema: 'claro', idioma: 'es' };

// Que crear closures complicados para compartir estado
function crearEstadoGlobal() {
  let usuario = null;
  let config = { tema: 'claro', idioma: 'es' };
  
  return {
    getUsuario: () => usuario,
    setUsuario: (u) => usuario = u,
    // ... más getters y setters
  };
}

Configuración que no cambia

Para constantes que usás en toda la aplicación:

// Directo y claro
window.API_BASE = 'https://api.miapp.com';
window.COLORES = {
  primario: '#007bff',
  secundario: '#6c757d',
  exito: '#28a745'
};

Debugging más fácil

Las variables globales son más fáciles de inspeccionar desde DevTools:

// Podés hacer console.log(window.estadoDebug) en cualquier momento
window.estadoDebug = {
  ultimaAccion: null,
  errores: [],
  tiempos: {}
};

Cómo decidir entre closures y variables globales

Usá closures cuando:

  • Necesitás múltiples "instancias" del mismo comportamiento
  • Querés encapsular estado privado
  • Estás creando una librería o componente reutilizable
  • El estado es específico de una funcionalidad

Usá variables globales cuando:

  • El dato se comparte entre muchas partes de la app
  • Es configuración que no cambia frecuentemente
  • Necesitás acceso fácil para debugging
  • La simplicidad es más importante que la encapsulación

Errores comunes con closures

El clásico problema del loop

// MAL - todas las funciones referencian la misma variable i
for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Imprime 3, 3, 3
  }, 100);
}

// BIEN - cada función tiene su propia copia de i
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Imprime 0, 1, 2
  }, 100);
}

// O usando closures explícitamente
for (var i = 0; i < 3; i++) {
  (function(j) {
    setTimeout(function() {
      console.log(j); // Imprime 0, 1, 2
    }, 100);
  })(i);
}

Memory leaks por referencias circulares

// Cuidado con esto
function crearHandler(elemento) {
  return function() {
    // El closure mantiene una referencia al elemento
    // Y el elemento mantiene una referencia al handler
    elemento.innerHTML = 'Clickeado';
  };
}

// Mejor
function crearHandler(elemento) {
  const id = elemento.id;
  return function() {
    document.getElementById(id).innerHTML = 'Clickeado';
  };
}

Preguntas frecuentes

¿Los closures afectan la performance? Mínimamente. El overhead es negligible en aplicaciones normales. Solo preocupate si estás creando miles de closures por segundo.

¿Puedo "romper" un closure desde afuera? No directamente. Las variables capturadas son privadas. Pero podés exponer métodos para modificar el estado interno si necesitás.

¿Es mejor usar modules que closures? Para organizar código grande, sí. Los modules son más claros y tienen mejor tooling. Usá closures para encapsular comportamiento específico dentro de modules.

¿Te gustó este artículo?

Descubre nuestros cursos y carreras para llevar tus habilidades al siguiente nivel.