Tema
Bucles
Imagina que tienes que mostrar 200 productos en una tienda, enviar un correo a cada cliente o sumar todos los precios de un carrito. Escribir la misma instrucción 200 veces sería absurdo. Para eso existen los bucles: repiten un bloque de código las veces que necesites. En esta lección aprenderás for, while, do...while, for...of y for...in, cuándo usar cada uno y cómo evitar el temido bucle infinito.
Concepto
Un bucle es como dar vueltas a una pista de atletismo: antes de cada vuelta te preguntas "¿ya terminé?". Si la respuesta es no, das otra vuelta; si es sí, te detienes.
Todo bucle tiene tres ingredientes:
- Un punto de inicio (por ejemplo, empezar a contar en 1).
- Una condición para seguir (mientras sea menor o igual a 10).
- Un avance que te acerca al final (sumar 1 en cada vuelta).
Si falta el avance, la condición nunca cambia y el bucle no termina jamás.
| Bucle | Úsalo cuando... |
|---|---|
for | Sabes cuántas veces repetir o necesitas el índice |
while | No sabes cuántas veces; repites mientras se cumpla algo |
do...while | Debe ejecutarse al menos una vez |
for...of | Recorres los valores de un array, string, etc. |
for...in | Recorres las claves (propiedades) de un objeto |
El bucle for
js
// for (inicio; condición; avance)
for (let i = 1; i <= 5; i++) {
console.log(`Vuelta número ${i}`);
}
// Vuelta número 1
// Vuelta número 2
// ...
// Vuelta número 5Paso a paso:
let i = 1→ se ejecuta una sola vez al inicio.i <= 5→ se revisa antes de cada vuelta. Si esfalse, el bucle termina.- Se ejecuta el bloque
{ ... }. i++→ se ejecuta al final de cada vuelta, y vuelve al paso 2.
Ejemplo: tabla de multiplicar
js
const numero = 7;
for (let i = 1; i <= 10; i++) {
console.log(`${numero} x ${i} = ${numero * i}`);
}
// 7 x 1 = 7
// 7 x 2 = 14
// ...
// 7 x 10 = 70Pruébalo en vivo: elige un número y hasta dónde quieres la tabla. Cada fila se genera con un bucle for que crea elementos en la página:
La parte importante del código de la demo:
js
tabla.innerHTML = ''; // limpiamos la tabla anterior
for (let i = 1; i <= limite; i++) {
const fila = document.createElement('div');
// Si i es par, agregamos una clase distinta (operador % y ternario)
fila.className = i % 2 === 0 ? 'fila par' : 'fila';
fila.innerHTML = `<span>${numero} × ${i}</span><b>${numero * i}</b>`;
tabla.appendChild(fila);
}Contar hacia atrás y en saltos
js
// Cuenta regresiva
for (let i = 10; i >= 1; i--) {
console.log(i);
}
console.log('¡Despegue! 🚀');
// De 5 en 5
for (let i = 0; i <= 100; i += 5) {
console.log(i); // 0, 5, 10, ..., 100
}Recorrer un array con índice
js
const productos = ['Café', 'Pan dulce', 'Chocolate'];
for (let i = 0; i < productos.length; i++) {
console.log(`${i + 1}. ${productos[i]}`);
}
// 1. Café
// 2. Pan dulce
// 3. ChocolateError común
Usar <= con length. Los índices empiezan en 0, así que el último es length - 1:
js
const colores = ['rojo', 'verde', 'azul'];
for (let i = 0; i <= colores.length; i++) {
console.log(colores[i]); // rojo, verde, azul, undefined ❌
}
// ✅ Usa i < colores.lengthEl bucle while
Repite mientras la condición sea verdadera. Ideal cuando no sabes de antemano cuántas vueltas habrá:
js
// ¿Cuántos meses tardo en ahorrar $10,000 si ahorro $1,500 al mes?
let ahorro = 0;
let meses = 0;
while (ahorro < 10000) {
ahorro += 1500;
meses++;
}
console.log(`Necesitas ${meses} meses. Tendrás $${ahorro}`);
// Necesitas 7 meses. Tendrás $10500El bucle do...while
Igual que while, pero la condición se revisa al final. Por eso el bloque siempre se ejecuta al menos una vez:
js
// Pedir un número hasta que el usuario escriba uno válido
let edad;
do {
edad = Number(prompt('¿Cuántos años tienes?'));
} while (Number.isNaN(edad) || edad <= 0);
console.log(`Tienes ${edad} años`);for...of: recorrer valores
Es la forma más cómoda y legible de recorrer arrays (y también strings, Map, Set...):
js
const carrito = [
{ nombre: 'Playera', precio: 250 },
{ nombre: 'Gorra', precio: 180 },
{ nombre: 'Sudadera', precio: 650 },
];
let total = 0;
for (const producto of carrito) {
console.log(`${producto.nombre}: $${producto.precio}`);
total += producto.precio;
}
console.log(`Total: $${total}`); // Total: $1080
// También funciona con strings
for (const letra of 'Hola') {
console.log(letra); // H, o, l, a
}Si necesitas el índice además del valor, usa entries():
js
const tareas = ['Diseñar', 'Programar', 'Publicar'];
for (const [indice, tarea] of tareas.entries()) {
console.log(`${indice + 1}. ${tarea}`);
}Buena práctica
Para recorrer arrays, prefiere for...of (o métodos como forEach, map y filter, que verás en Métodos de arrays). Usa el for clásico sólo cuando necesitas control fino del índice: saltos, recorrer al revés o modificar posiciones.
for...in: recorrer propiedades de un objeto
for...in recorre las claves de un objeto:
js
const usuario = {
nombre: 'Ana',
email: 'ana@correo.com',
plan: 'Pro',
};
for (const clave in usuario) {
console.log(`${clave}: ${usuario[clave]}`);
}
// nombre: Ana
// email: ana@correo.com
// plan: ProError común
No uses for...in con arrays. Te da los índices como strings ('0', '1'...) y puede incluir propiedades heredadas. Para arrays usa for...of. Para objetos, una alternativa moderna es Object.entries():
js
for (const [clave, valor] of Object.entries(usuario)) {
console.log(clave, valor);
}break y continue
breaksale del bucle por completo.continuesalta a la siguiente vuelta, ignorando el resto del bloque.
js
const pedidos = [
{ id: 1, estado: 'pagado' },
{ id: 2, estado: 'cancelado' },
{ id: 3, estado: 'pagado' },
{ id: 4, estado: 'fraude' },
{ id: 5, estado: 'pagado' },
];
for (const pedido of pedidos) {
if (pedido.estado === 'cancelado') {
continue; // ignoramos este y seguimos con el siguiente
}
if (pedido.estado === 'fraude') {
console.log(`⚠️ Pedido ${pedido.id} sospechoso. Deteniendo proceso.`);
break; // salimos del bucle
}
console.log(`Enviando pedido ${pedido.id}`);
}
// Enviando pedido 1
// Enviando pedido 3
// ⚠️ Pedido 4 sospechoso. Deteniendo proceso.Un uso clásico de break: buscar algo y detenerse al encontrarlo.
js
const correos = ['luis@mail.com', 'ana@mail.com', 'sofia@mail.com'];
let encontrado = false;
for (const correo of correos) {
if (correo === 'ana@mail.com') {
encontrado = true;
break; // no tiene caso seguir buscando
}
}
console.log(encontrado); // trueBucles infinitos
Un bucle infinito ocurre cuando la condición nunca se vuelve falsa. El navegador se congela y la pestaña deja de responder.
js
// ❌ Olvidamos el avance: i siempre vale 0
let i = 0;
while (i < 5) {
console.log(i);
// falta i++
}
// ❌ El avance va en la dirección equivocada
for (let j = 10; j > 0; j++) {
// j crece y siempre será > 0
}Si se te congela la página
Cierra la pestaña o, en Chrome, abre el Administrador de tareas del navegador (Shift + Esc) y finaliza esa pestaña. Luego revisa tu condición y tu avance.
A veces un bucle "infinito" es intencional, pero siempre con una salida clara:
js
let intentos = 0;
while (true) {
intentos++;
const numero = Math.floor(Math.random() * 10);
if (numero === 7) {
console.log(`¡Salió el 7 en ${intentos} intentos!`);
break; // salida garantizada (tarde o temprano)
}
}Casos de uso reales
- Generar las tarjetas de productos de una tienda a partir de un array.
- Sumar el total de un carrito con
for...of. - Crear las opciones de un
<select>(por ejemplo, años del 1950 al actual). - Validar todos los campos de un formulario y detenerse en el primer error con
break. - Reintentar una operación mientras falle (con un límite de intentos).
js
// Llenar un select de años de nacimiento
const select = document.querySelector('#anio');
const anioActual = new Date().getFullYear();
for (let anio = anioActual; anio >= 1950; anio--) {
const opcion = document.createElement('option');
opcion.value = anio;
opcion.textContent = anio;
select.appendChild(opcion);
}Ejercicios
- Imprime los números pares del 1 al 20 usando un
fory el operador%. - Dado
const precios = [120, 45.5, 300, 89.9];, calcula el total confor...ofy el precio más alto. - Usa
whilepara calcular cuántos años tarda en duplicarse una inversión de $10,000 con 8 % de interés anual compuesto. - Recorre el objeto
const inventario = { manzanas: 12, peras: 0, uvas: 5 };confor...iny muestra sólo las frutas con existencias, usandocontinue.
Ver solución
1.
js
for (let i = 1; i <= 20; i++) {
if (i % 2 !== 0) continue;
console.log(i); // 2, 4, 6, ..., 20
}2.
js
const precios = [120, 45.5, 300, 89.9];
let total = 0;
let maximo = precios[0];
for (const precio of precios) {
total += precio;
if (precio > maximo) maximo = precio;
}
console.log(`Total: $${total.toFixed(2)}`); // Total: $555.40
console.log(`Más caro: $${maximo}`); // Más caro: $3003.
js
let dinero = 10000;
let anios = 0;
while (dinero < 20000) {
dinero *= 1.08;
anios++;
}
console.log(`Se duplica en ${anios} años`); // Se duplica en 10 años4.
js
const inventario = { manzanas: 12, peras: 0, uvas: 5 };
for (const fruta in inventario) {
if (inventario[fruta] === 0) continue;
console.log(`${fruta}: ${inventario[fruta]}`);
}
// manzanas: 12
// uvas: 5Resumen
- Todo bucle necesita inicio, condición y avance.
for: cuando sabes cuántas vueltas o necesitas el índice.while: repite mientras se cumpla una condición;do...whilese ejecuta al menos una vez.for...of: recorre valores de arrays y strings (la opción más legible).for...in: recorre claves de objetos (no lo uses con arrays).breaksale del bucle;continuesalta a la siguiente vuelta.- Evita bucles infinitos revisando que la condición pueda volverse falsa.
Siguiente: Funciones