Ciclos while, for y do-while: diferencias y cuándo usar cada uno
En este artículo
Un ciclo o bucle es una estructura que repite un bloque de código mientras se cumpla una condición. Sin bucles, procesar una lista de mil elementos exigiría escribir mil líneas iguales.
Hay tres formas básicas —while, for y do-while— y todas hacen lo mismo en el fondo. La diferencia está en cuándo se comprueba la condición y en qué situación resulta más legible cada una.
Las tres partes que tiene todo bucle
Aunque la sintaxis cambie, siempre hay estos tres elementos. Si falta uno, el bucle falla:
- Inicialización. El punto de partida: una variable contador, un índice, un valor inicial.
- Condición. La pregunta que se hace en cada vuelta. Mientras dé verdadero, se repite.
- Actualización. Lo que cambia en cada vuelta para que la condición acabe siendo falsa.
Olvidar la actualización es la causa del error más temido: el bucle infinito.
El ciclo while
Comprueba la condición antes de ejecutar el bloque. Si la condición es falsa desde el principio, el cuerpo no se ejecuta ni una vez.
let contador = 1; // inicialización
while (contador <= 5) { // condición
console.log(contador);
contador++; // actualización
}
Imprime del 1 al 5. Cuando contador llega a 6, la condición es falsa y el bucle termina.
Cuándo usarlo: cuando no sabes de antemano cuántas vueltas harán falta. Leer un archivo hasta que se acabe, esperar a que un usuario introduzca un dato válido, procesar una cola hasta vaciarla.
let respuesta = "";
while (respuesta !== "si" && respuesta !== "no") {
respuesta = pedirDato("¿Continuar? (si/no)");
}
El ciclo for
Hace lo mismo que while, pero agrupa las tres partes en una sola línea. Es más compacto y más difícil de romper por olvido.
for (let i = 1; i <= 5; i++) {
console.log(i);
}
Las tres partes, separadas por punto y coma: let i = 1 es la inicialización, i <= 5 la condición y i++ la actualización.
Cuándo usarlo: cuando sabes cuántas repeticiones necesitas, o cuando recorres una colección por posición.
const nombres = ["Ana", "Luis", "Sara"];
for (let i = 0; i < nombres.length; i++) {
console.log(nombres[i]);
}
Fíjate en dos detalles que importan: se empieza en 0 porque los índices arrancan en cero, y la condición es < y no <=. Con tres elementos, los índices válidos son 0, 1 y 2. Usar <= intentaría acceder al índice 3, que no existe. Es el llamado error de uno en uno, y es de los más frecuentes al aprender.
Variantes modernas del for
Casi todos los lenguajes tienen una forma de recorrer colecciones sin manejar índices:
// JavaScript
for (const nombre of nombres) { console.log(nombre); }
// Python
for nombre in nombres: print(nombre)
// Java
for (String nombre : nombres) { System.out.println(nombre); }
// PHP
foreach ($nombres as $nombre) { echo $nombre; }
Cuando solo necesitas los valores y no las posiciones, esta forma es más clara y elimina de raíz los errores de índice.
El ciclo do-while
La diferencia con while es una sola, pero decisiva: comprueba la condición después de ejecutar el bloque. Por tanto el cuerpo se ejecuta siempre al menos una vez.
let opcion;
do {
opcion = mostrarMenu();
procesar(opcion);
} while (opcion !== 0);
Tiene sentido: el menú hay que mostrarlo al menos una vez antes de poder saber qué eligió el usuario.
Cuándo usarlo: menús, validación de entradas, cualquier proceso que deba ejecutarse una vez y repetirse solo si hace falta.
Nota para quien programa en Python: do-while no existe. Se simula así:
while True:
opcion = mostrar_menu()
procesar(opcion)
if opcion == 0:
break
Comparación directa
| while | for | do-while | |
|---|---|---|---|
| Comprueba la condición | Antes | Antes | Después |
| Ejecuciones mínimas | 0 | 0 | 1 |
| Nº de vueltas conocido | No hace falta | Sí, normalmente | No hace falta |
| Uso típico | Condición abierta | Recorrer colecciones | Menús y validación |
Lo importante: los tres son intercambiables. Cualquier for se puede escribir como while. La elección es de legibilidad, no de capacidad.
Controlar el bucle desde dentro
break sale del bucle inmediatamente:
for (let i = 0; i < productos.length; i++) {
if (productos[i].id === buscado) {
encontrado = productos[i];
break; // ya lo tenemos, no seguimos
}
}
continue salta a la siguiente vuelta sin ejecutar el resto del bloque:
for (const pedido of pedidos) {
if (pedido.cancelado) continue; // este lo ignoramos
procesar(pedido);
}
Errores frecuentes
1. Bucle infinito
let i = 0;
while (i < 10) {
console.log(i);
// falta i++
}
La condición nunca se vuelve falsa. El programa se cuelga. Antes de ejecutar, comprueba siempre que algo dentro del bucle modifique la variable de la condición.
Una variante más sutil:
for (let i = 0; i != 10; i += 3) { ... }
Aquí i toma los valores 0, 3, 6, 9, 12… y nunca es exactamente 10. Con < en lugar de != no pasaría.
2. Modificar una colección mientras la recorres
for (let i = 0; i < lista.length; i++) {
if (lista[i].borrar) lista.splice(i, 1); // problema
}
Al eliminar un elemento, los siguientes se desplazan y el índice se salta uno. Recorre al revés, o mejor, crea una lista nueva con filter.
3. Declarar la variable fuera cuando no hace falta
Usar let i dentro del for limita su alcance al bucle. Declararla fuera la deja viva después, con efectos difíciles de rastrear.
4. Calcular lo mismo en cada vuelta
// mal: length se consulta en cada vuelta
for (let i = 0; i < lista.length; i++) { ... }
// mejor cuando la lista es grande y no cambia
const n = lista.length;
for (let i = 0; i < n; i++) { ... }
Bucles anidados
Un bucle dentro de otro. Se usan para recorrer matrices o generar combinaciones:
for (let fila = 0; fila < 3; fila++) {
for (let col = 0; col < 3; col++) {
console.log(matriz[fila][col]);
}
}
Ojo con el coste: si el externo da 1.000 vueltas y el interno otras 1.000, se ejecuta un millón de veces. Con tres niveles anidados, mil millones. Los bucles anidados son la causa más común de programas que funcionan con datos de prueba y se arrastran con datos reales.
Preguntas frecuentes
¿Cuál es más rápido, while o for?
Ninguno. Compilan a prácticamente lo mismo. Elige por claridad.
¿Cuándo uso do-while?
Cuando el bloque deba ejecutarse al menos una vez pase lo que pase. Menús y validación de entrada son los casos clásicos.
¿Cómo salgo de un bucle infinito en ejecución?
En la terminal, Ctrl+C. En el navegador, cerrando la pestaña. Después revisa qué variable debía cambiar y no cambia.
¿Es mejor usar for o métodos como map y filter?
Para transformar o filtrar colecciones, map y filter son más legibles y evitan errores de índice. Para lógica compleja o salidas anticipadas, el bucle clásico sigue siendo más claro.
¿Aprendiendo a programar? En nuestro catálogo de cursos técnicos tienes formación desde cero, con acceso inmediato y de por vida.