Desarrollo Web

Bucles en JavaScript: for, while y do while explicados fácil

Jairo
6 min de lectura
Bucles en JavaScript: for, while y do while explicados fácil

1) Qué es un bucle en JavaScript (y cómo evitar los infinitos)

Definición simple + ejemplo mínimo

Un bucle es una estructura que repite un bloque de código mientras se cumpla una condición. Me gusta explicarlo así: si hay una tarea repetitiva con una condición de salida, úsalo. En mi día a día, cuando tengo que procesar listas, validar entradas o calcular resultados paso a paso, tiro de bucles.

Un ejemplo mínimo con while:

let i = 0;
while (i < 3) {
  console.log(i);
  i++; // actualización
}

Aquí aparecen siempre tres piezas mentales: inicialización, condición y actualización. En mi caso, esa tríada me evita el 90% de errores tontos.

Nota desde la práctica: como me contaste, “los bucles son para tareas repetitivas con base en una condición”. Esa frase es oro, y la usaremos como brújula en todas las secciones.

Señales de bucle infinito y cómo cortarlo (break, condición, contadores)

Los bucles infinitos ocurren cuando la condición nunca se vuelve falsa o la actualización no progresa. Señales típicas: la CPU se dispara, la página se congela y los logs no paran.

Checklist rápido para evitarlos:

  1. ¿La variable que controla el bucle cambia en cada iteración?
  2. ¿La condición puede volverse falsa con el tiempo?
  3. ¿Hay una vía de escape (break) para casos excepcionales?
  4. ¿Has limitado el número máximo de iteraciones en procesos sensibles?

Ejemplo antivirus de infinitos con tope duro:

let intentos = 0;
const LIMITE = 1000;
while (condicionSigueSiendoVerdadera()) {
  // ... trabajo ...
  if (++intentos > LIMITE) break; // vía de escape
}

Cuando probé esto en un proyecto que hacía scraping, me salvó de “espirales” donde la condición tardaba demasiado en romperse.

2) for: cuando sabes cuántas veces

Estructura (inicialización, condición, actualización)

for brilla cuando conoces cuántas repeticiones quieres o cuando iteras índices:

for (let i = 0; i < n; i++) {
  // bloque a repetir n veces
}

Piensa en for como una frase bien puntuada: empiezo en i=0; sigo mientras i<n; al final, i++.

Ejemplo práctico: sumar del 1 al 100 de 2 en 2 (y variante decreciente)

Tu ejemplo clásico:

let suma = 0;
for (let i = 1; i <= 100; i += 2) {
  suma += i;
}
console.log(suma);

Variante hacia atrás (útil para recorrer arrays cuando vas eliminando elementos):

for (let i = arr.length - 1; i >= 0; i--) {
  // trabajar de derecha a izquierda
}

Aquí meto una cuña de experiencia: cuando expliqué este patrón a un equipo junior, entendieron por fin por qué “inicialización, condición y expresión final” importan tanto. Si una de las tres falla, el bucle no hace lo que esperas.

Errores comunes (límites de array, off-by-one)

  • Off-by-one: usar < vs <=. Si una lista tiene 10 elementos (0–9), i < arr.length es lo correcto.
  • Mutar la longitud dentro del bucle: si haces arr.push() o arr.splice() mientras iteras con i++, piensa en recorrer hacia atrás o en clonar primero.
  • Trabajo pesado dentro del bucle: saca cálculos invariantes fuera (por ejemplo, const len = arr.length; antes del for).

3) while: cuando la condición manda

Sintaxis y patrón típico

while es ideal cuando no sabes cuántas veces ocurrirá algo, pero sí bajo qué condición debería seguir:

let seguir = true;
while (seguir) {
  // ...
  seguir = decideSiContinuar(); // actualiza estado
}

Validaciones y ciclos de espera controlados

Muy útil para validar entrada o para reintentos con límites:

let input;
let intentos = 0;
do {
  input = obtenerValorUsuario();
} while (!esValido(input) && ++intentos < 3);

Aunque aquí usé do…while (lo veremos enseguida), la lógica de “seguir mientras no sea válido” es la esencia del while.

Cómo no caer en bucles infinitos

Con while es fácil olvidar actualizar el estado que alimenta la condición. Un truco que uso: en revisiones de código, busco explícitamente dónde cambia la variable que controla el while. Si no la encuentro en dos segundos, pido refactor.

En mi experiencia, los cuelgues por bucles infinitos “pueden dañar o hacer muy lenta” la app. Un break preventivo y logs de progreso cada X iteraciones me han ahorrado horas de depuración.

4) do…while: cuando necesitas ejecutar al menos una vez

Sintaxis y casos clásicos (menús, reintentos de input)

do…while ejecuta el bloque primero y luego verifica la condición:

let opcion;
do {
  opcion = mostrarMenuYLeer();
} while (!["a","b","c"].includes(opcion));

Casos típicos:

  • Pedir al menos una entrada al usuario.
  • Hacer un intento de red y, si falla, reintentar hasta N veces.
  • Ejecutar un paso obligatorio y después decidir si repetir.

Comparativa rápida con while

  • while: primero compruebo, luego ejecuto.
  • do…while: primero ejecuto, luego compruebo.
Cuando enseño esto, repito: si necesitas una pasada garantizada (p. ej., pintar un primer frame), do…while encaja.

5) Otras formas de iterar: for…of y for…in (cuándo sí y cuándo no)

Iterables y arrays (for…of)

for…of recorre valores de cualquier iterable (arrays, strings, Maps, Sets):

for (const valor of miArray) {
  console.log(valor);
}

Ventajas: legible, evita manejar índices cuando no los necesitas. Ideal para procesar elementos de una lista sin tocar posiciones.

Objetos (for…in) y advertencias en arrays

for…in recorre propiedades enumerables de un objeto:

const usuario = { id: 1, nombre: "Ada" };
for (const clave in usuario) {
  console.log(clave, usuario[clave]);
}

Advertencia: no lo uses para arrays si podrían tener propiedades añadidas o prototipos especiales; podrías iterar cosas que no son elementos.

Selección de la estructura adecuada (mini diagrama)

  • ¿Necesitas índice? → for.
  • ¿Solo valores de un iterable? → for…of.
  • ¿Propiedades de objeto plano? → for…in (o mejor Object.keys/entries + for…of).
  • ¿No sabes cuántas veces pero hay condición? → while.
  • ¿Mínimo una vez? → do…while.

6) Cómo elegir el bucle correcto (guía rápida + checklist)

Guía rápida para elegir

  • Necesitas índice o control fino del inicio/fin/paso → Usa for. (Si vas a eliminar elementos mientras recorres, considera el for inverso de derecha a izquierda).
  • Solo te interesan los valores de un iterable (Array, String, Map, Set) → Usa for…of por legibilidad.
  • Vas a recorrer propiedades de un objeto plano → Prefiere Object.entries/keys + for…of; si usas for…in, filtra con hasOwnProperty.
  • No sabes cuántas repeticiones habrá; manda la condición → Usa while.
  • Debes ejecutar al menos una vez y luego decidir → Usa do…while.
Consejito práctico: si dudas entre dos, escribe un prototipo de 5 líneas con logs y revisa cuál te deja el código más claro (no solo más corto).

Checklist de 5 preguntas antes de iterar

  1. ¿Hay límite claro de repeticiones?
  2. ¿Necesito índice o solo valores?
  3. ¿La condición depende de estado externo (E/S, red)?
  4. ¿Tengo una salida de emergencia (break/límite de intentos)?
  5. ¿Puedo mover cálculos fuera del bucle para rendir mejor?

7) Buenas prácticas y rendimiento

Legibilidad vs micro-optimización

Prefiero código que se entienda. Si no hay evidencia de que el bucle es un cuello de botella, prioriza claridad (for…of sobre trucos crípticos). Cuando medí mejoras, muchas “micro-optimizaciones” daban ganancias marginales frente a cambiar el algoritmo o la ubicación del trabajo pesado.

Evitar trabajo innecesario en cada iteración

  • Calcula const len = arr.length; si accedes mucho a length en for clásico.
  • Evita crear objetos/funciones dentro del bucle si puedes precomputarlos.
  • Saca I/O (DOM, red) fuera del bucle: acumula y aplica en lote.

Tests rápidos en la consola

Pequeño patrón que uso para probar ideas:

console.time("loop");
let total = 0;
for (let i = 0; i < 1e6; i++) total += i;
console.timeEnd("loop");

No es un benchmark científico, pero te da una sensación de impacto al iterar.

En mi experiencia, tener un “rail” mental (init–condición–update) y evitar infinitos me ha dado resultados estables y una UI fluida.

8) Ejercicios rápidos para afianzar

1) Suma de pares hasta N

Reto: dada N, suma los números pares de 0 a N usando for. <details> <summary>Solución</summary> 

function sumaPares(N) {
  let s = 0;
  for (let i = 0; i <= N; i += 2) s += i;
  return s;
}

</details> 

2) Validación con reintentos

Reto: pide un valor hasta que pase esValido(x) o falles 3 veces. Usa do…while. <details> <summary>Solución</summary> 

function pedirValido(obtener, esValido, max=3) {
  let x, intentos = 0;
  do {
    x = obtener();
    intentos++;
  } while (!esValido(x) && intentos < max);
  return esValido(x) ? x : null;
}

</details> 

3) Recorrer objeto y crear array de pares

Reto: con for…in, devuelve [[clave, valor], ...] de un objeto. <details> <summary>Solución</summary> 

function pares(obj) {
  const out = [];
  for (const k in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, k)) {
      out.push([k, obj[k]]);
    }
  }
  return out;
}

</details> 

Conclusión

Los bucles son el motor de las tareas repetitivas en JavaScript. Si recuerdas el triángulo inicialización–condición–actualización y eliges la estructura adecuada (for, while, do…while, for…of, for…in) según el escenario, evitarás cuelgues, escribirás menos bugs y tu código será más legible. En mi experiencia, los infinitos son el enemigo: añade límites, break y logs, y todo fluirá.


JavaScript

Jairo

Comentarios (0)

No hay comentarios aún. ¡Sé el primero en comentar!

Envíame un comentario

🍪 Utilizamos cookies para mejorar tu experiencia de navegación, analizar el tráfico del sitio y personalizar el contenido. Al continuar navegando, aceptas nuestro uso de cookies. Más información