Saltar al contenido
bucles.js · devschool

Bucles en JavaScript

Lección 8 de 38 · 10 min de lectura · Actualizado el

En esta lección
  1. for: cuando sabes cuántas veces
  2. for...of: recorrer una lista
  3. for...in: recorrer las propiedades de un objeto
  4. while: mientras se cumpla algo
  5. do...while: al menos una vez
  6. break y continue
  7. Bucles anidados
  8. Cuidado con los bucles infinitos
  9. Otros errores frecuentes
  10. Qué bucle elegir
  11. Resumen

Un bucle repite un bloque de código varias veces. En lugar de escribir diez console.log, escribes uno y lo repites. Los bucles están en todas partes: mostrar los productos de una tienda, sumar las notas de una clase, reintentar una conexión, pedir una contraseña hasta que sea correcta… En esta lección verás todos los bucles de JavaScript, cómo controlarlos con break y continue, y cómo elegir el adecuado para cada caso.

for: cuando sabes cuántas veces

for (let i = 0; i < 5; i++) {
  console.log("Vuelta número", i);
}

Entre los paréntesis hay tres partes separadas por ;:

  1. Inicio: let i = 0. Se ejecuta una vez, al empezar.
  2. Condición: i < 5. Se comprueba antes de cada vuelta. Si es falsa, el bucle termina.
  3. Paso: i++. Se ejecuta al final de cada vuelta.

Este bucle muestra 0, 1, 2, 3 y 4. Cuando i vale 5, la condición falla y se sale. Cada repetición se llama iteración y la variable i (de índice) es el contador.

En programación se empieza a contar desde 0, porque así funcionan las posiciones de los arrays.

El paso no tiene por qué ser i++. Puedes contar hacia atrás o de dos en dos:

// Cuenta atrás
for (let i = 3; i > 0; i--) {
  console.log(i); // 3, 2, 1
}
console.log("¡Despegue!");

// Números pares hasta 10
for (let i = 0; i <= 10; i += 2) {
  console.log(i); // 0, 2, 4, 6, 8, 10
}

Recorrer un array con for

Con el índice puedes acceder a cada posición de un array. La condición usa length, el número de elementos:

const notas = [7, 4, 9, 6];
let suma = 0;

for (let i = 0; i < notas.length; i++) {
  suma += notas[i];
}

console.log("Media:", suma / notas.length); // Media: 6.5

Fíjate en i < notas.length y no i <= notas.length: con 4 notas, las posiciones van de 0 a 3. Este for clásico es útil cuando necesitas el índice, por ejemplo para numerar o para recorrer al revés.

for...of: recorrer una lista

La forma más cómoda de pasar por todos los elementos de un array:

const alumnos = ["Ana", "Luis", "Marta"];

for (const alumno of alumnos) {
  console.log("Hola,", alumno);
}

En cada vuelta, alumno toma el valor del siguiente elemento. No hay índice que gestionar ni riesgo de pasarte de la última posición. Puedes usar const porque en cada vuelta se crea una variable nueva.

for...of funciona con cualquier cosa iterable: arrays, cadenas de texto, Set y Map…

for (const letra of "sol") {
  console.log(letra); // s, o, l
}

¿Y si también quieres la posición? Usa entries():

const podio = ["Irene", "Pablo", "Sara"];

for (const [posicion, nombre] of podio.entries()) {
  console.log(`${posicion + 1}.º ${nombre}`);
}
// 1.º Irene
// 2.º Pablo
// 3.º Sara

La sintaxis [posicion, nombre] se llama desestructuración y la verás a fondo en desestructuración y spread.

for...in: recorrer las propiedades de un objeto

for...in recorre las claves (los nombres de las propiedades) de un objeto:

const horario = { lunes: "Spinning", miercoles: "Yoga", viernes: "Crossfit" };

for (const dia in horario) {
  console.log(`${dia}: ${horario[dia]}`);
}
// lunes: Spinning
// miercoles: Yoga
// viernes: Crossfit

Por qué no usar for...in con arrays

Funciona, pero da problemas:

const precios = [10, 20, 30];
let total = 0;

for (const i in precios) {
  console.log(typeof i); // string
  total += i;            // concatena textos, no suma números
}

console.log(total); // 0012
  • Las claves que devuelve son textos ("0", "1", "2"), no números. Operaciones como i + 1 dan resultados inesperados.
  • Recorre también cualquier propiedad extra que alguien haya añadido al array.

Regla fácil: for...of para arrays, for...in para objetos.

while: mientras se cumpla algo

Cuando no sabes cuántas vueltas harán falta, solo la condición para seguir:

let dinero = 100;
let meses = 0;

while (dinero < 200) {
  dinero = dinero * 1.1; // crece un 10 %
  meses++;
}

console.log(`Tardas ${meses} meses en doblar tu dinero`); // Tardas 8 meses...

while comprueba la condición antes de cada vuelta. Si es falsa desde el principio, el bloque no se ejecuta ni una vez.

Otro caso típico: repetir hasta que ocurra algo aleatorio.

let tiradas = 0;
let dado = 0;

while (dado !== 6) {
  dado = Math.floor(Math.random() * 6) + 1;
  tiradas++;
}

console.log(`Ha salido un 6 tras ${tiradas} tiradas`);

do...while: al menos una vez

do...while ejecuta el bloque primero y comprueba la condición después. Por eso siempre se ejecuta al menos una vez:

let intento = 10;

do {
  console.log("Intento", intento); // Intento 10
  intento++;
} while (intento < 5);

Aunque 10 < 5 es falso, el bloque se ejecutó una vez. Es útil cuando la condición depende de algo que ocurre dentro, como pedir un dato al usuario:

let codigo;
do {
  codigo = prompt("Introduce el código de 4 cifras"); // solo en el navegador
} while (codigo !== null && codigo.length !== 4);

Se usa poco, pero conviene reconocerlo. Fíjate en el ; final tras el while.

break y continue

  • break sale del bucle inmediatamente.
  • continue salta a la siguiente vuelta, sin ejecutar lo que queda del bloque.
for (let i = 1; i <= 10; i++) {
  if (i % 2 === 0) continue; // salta los pares
  if (i > 7) break;          // para al pasar de 7
  console.log(i);            // 1, 3, 5, 7
}

break es perfecto para dejar de buscar en cuanto encuentras algo:

const reservas = ["Ana", "Luis", "Marta", "Jorge"];
let encontrada = false;

for (const nombre of reservas) {
  console.log("Comprobando", nombre);
  if (nombre === "Luis") {
    encontrada = true;
    break; // no hace falta mirar el resto
  }
}
console.log(encontrada); // true (solo comprueba Ana y Luis)

Para buscar en arrays también existen métodos más cortos, como find o includes, que verás en métodos de arrays.

Etiquetas

break solo sale del bucle más cercano. Si tienes un bucle dentro de otro y quieres salir de los dos, puedes ponerle una etiqueta al exterior:

externo: for (let fila = 1; fila <= 3; fila++) {
  for (let col = 1; col <= 3; col++) {
    if (fila * col === 4) break externo;
    console.log(fila, col);
  }
}
// 1 1, 1 2, 1 3, 2 1

Se usan muy poco. Normalmente queda más claro meter los bucles en una función y salir con return.

Bucles anidados

Un bucle dentro de otro: por cada vuelta del exterior, el interior da todas sus vueltas. Sirven para trabajar con tablas o combinaciones:

const tallas = ["S", "M"];
const colores = ["negro", "blanco"];

for (const talla of tallas) {
  for (const color of colores) {
    console.log(`Camiseta ${talla} ${color}`);
  }
}
// Camiseta S negro
// Camiseta S blanco
// Camiseta M negro
// Camiseta M blanco

Con 2 tallas y 2 colores hay 4 vueltas en total. Ojo: con 1000 × 1000 serían un millón. Los bucles anidados se vuelven lentos rápidamente con muchos datos.

Cuidado con los bucles infinitos

Si la condición nunca llega a ser falsa, el bucle no termina y la página se congela:

let i = 0;
while (i < 5) {
  console.log(i);
  // falta i++ → i siempre vale 0 → bucle infinito
}

Antes de ejecutar un while, comprueba que algo dentro del bucle acerca la condición a ser falsa. Causas típicas:

  • Olvidar el i++ en un while.
  • Equivocarse de dirección: for (let i = 10; i > 0; i++) nunca baja de 10.
  • Una condición que no puede cumplirse, como while (x !== 10) sumando de 3 en 3 desde 0.

A veces se escribe un bucle infinito a propósito con while (true) y se sale con break cuando se cumple algo. Es válido, pero asegúrate de que ese break llega.

Consejo: si la pestaña del navegador se queda congelada, ciérrala. En Node, pulsa Ctrl + C en la terminal para parar el programa.

Otros errores frecuentes

  • Pasarte una posición: i <= array.length lee una posición que no existe y obtienes undefined.
  • Usar const en el contador del for clásico: for (const i = 0; i < 5; i++) da TypeError en cuanto intenta hacer i++. En for...of y for...in sí puedes usar const.
  • Poner ; justo después del for: for (let i = 0; i < 3; i++); repite un bloque vacío y el código entre llaves se ejecuta solo una vez.
  • Modificar el array mientras lo recorres (añadir o borrar elementos): el número de vueltas cambia y se saltan elementos. Mejor crea un array nuevo.

Qué bucle elegir

SituaciónBucleEjemplo
Recorrer todos los elementos de un arrayfor...ofmostrar cada producto
Necesitas el índice, contar al revés o saltar de 2 en 2fornumerar filas, cuenta atrás
Recorrer las propiedades de un objetofor...in o Object.entriesmostrar un horario
No sabes cuántas vueltas, depende de una condiciónwhilerepetir hasta sacar un 6
Debe ejecutarse al menos una vezdo...whilepedir un dato hasta que sea válido
Transformar o filtrar un arraymap, filter…precios con IVA

Para trabajar con arrays, en el código moderno se usan mucho los métodos forEach, map o filter, que hacen el bucle por ti y dejan el código más corto. Los tienes en map, filter, reduce y otros métodos. Aun así, entender los bucles clásicos es imprescindible: esos métodos son bucles por dentro.

Resumen

  • for (inicio; condición; paso) repite un número conocido de veces.
  • for...of recorre los valores de un array, una cadena o cualquier iterable.
  • for...in recorre las claves de un objeto; evítalo con arrays.
  • while repite mientras se cumpla una condición; do...while se ejecuta al menos una vez.
  • break sale del bucle y continue pasa a la siguiente vuelta.
  • En un bucle anidado, el interior da todas sus vueltas por cada vuelta del exterior.
  • Asegúrate siempre de que la condición llegará a ser falsa.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

bucles.js
Consola

Pon a prueba lo que has aprendido

[JavaScript] ¿Cuántas veces se muestra "hola"?
for (let i = 0; i < 3; i++) {
  console.log("hola");
}

[JavaScript] ¿Qué muestra este código?
for (let i = 1; i <= 10; i++) {
  if (i % 2 === 0) continue;
  if (i > 5) break;
  console.log(i);
}

[JavaScript] ¿Qué muestra este código?
let vueltas = 0;
for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 4; j++) {
    vueltas++;
  }
}
console.log(vueltas);

[JavaScript] Quieres recorrer los elementos de un array. ¿Por qué es mejor for...of que for...in?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.