Aprende leyendo en orden

Repetir según una condición — while, do...while, break y continue

Aprende while y do...while en JavaScript: repetir cuando no sabes cuántas veces, evitar bucles infinitos y cuándo usar continue o break.

Dar un lugar a quien está en la lista de espera cada vez que se libera una reserva, o seguir comprando mientras el saldo alcance: en tareas así sabes cuándo parar, pero no puedes saber de antemano cuántas veces vas a repetir.

En este artículo verás while y do...while, que repiten según una condición; continue, que se salta una vuelta, y break, que sale del bucle.

Repetir sin un número fijo de vueltas — while y la actualización de la condición

Supón que se liberan algunos lugares y quieres dárselos en orden a quienes encabezan la lista de espera. Cada persona que pasa ocupa un lugar, y paras en cuanto quedan 0 lugares. Lo que detiene el bucle es un estado ("mientras queden lugares libres"), no un número de vueltas, así que un bucle for que cuenta no lo expresa de forma natural.

Un bucle while (una sentencia que repite el cuerpo entre llaves mientras se cumple la condición entre paréntesis) solo lleva una condición entre paréntesis. La condición se comprueba en cada vuelta, antes de entrar al cuerpo.

El valor inicial lo escribes tú antes del bucle, y la actualización de la variable que comprueba la condición también la escribes tú, dentro del cuerpo.

const waitingList = ["Ana", "Carlos", "Lucía"];   // lista de espera
let openSeats = 2;                                 // lugares libres

// Da un lugar solo mientras queden lugares libres
while (openSeats > 0) {
  const name = waitingList.shift();
  openSeats--;   // equivale a openSeats = openSeats - 1
  console.log(`${name} obtiene un lugar (lugares libres: ${openSeats})`);
}
// Ana obtiene un lugar (lugares libres: 1)
// Carlos obtiene un lugar (lugares libres: 0)

console.log(`Siguen en espera: ${waitingList.length}`);   // Siguen en espera: 1
Un bucle while que termina y otro que no
CondiciónopenSeats > 0El cuerpo daun lugaropenSeats--se actualizaEn 0, la condiciónno se cumpleCondiciónopenSeats > 0El cuerpo daun lugarSin actualizaciónSe queda en 2,nunca termina
Si el cuerpo disminuye la variable que comprueba la condición, tarde o temprano la condición deja de cumplirse y el bucle termina. Si no la disminuye, la comprobación da el mismo resultado cada vez y el cuerpo se sigue ejecutando.

En un bucle for, la expresión de actualización tiene un lugar fijo dentro de los paréntesis, pero con while decides tú en qué parte del cuerpo ponerla. La contrapartida de esa libertad es que nada te impide olvidarla: el código sigue siendo perfectamente válido sin la actualización.

Si olvidas la actualización, el bucle nunca se detiene

Si la condición nunca deja de cumplirse, el cuerpo se repite para siempre. Si te olvidas de escribir openSeats--, los lugares libres se quedan en 2, así que la comprobación siempre da el mismo resultado. La consola muestra un aviso de tiempo agotado a los 15 segundos, pero el bucle no se detiene, y los demás ejercicios tampoco funcionarán hasta que recargues la página. Cambia siempre en algún punto del cuerpo la variable que comprueba la condición.

Usa un saldo de puntos para comprar todas las unidades que puedas del mismo artículo. balance y unitPrice ya están declaradas.

① Prepara una variable que empiece en 0 para contar cuántas unidades compraste.

② Escribe la condición del bucle para que se repita solo mientras el saldo alcance para una unidad más.

③ En cada vuelta, resta del saldo, aumenta el contador e imprime "Artículo ◯ (puntos restantes: ◯)".

④ Después del bucle, imprime en una línea la cantidad comprada y los puntos restantes.

(Si se ejecuta correctamente, aparecerá una explicación.)

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Ejecutar una vez primero — el orden de comprobación en do...while

Cuando falla el envío de una notificación, la reintentas varias veces hasta que salga bien. Tienes que enviarla al menos una vez para tener un resultado que comprobar, pero while comprueba su condición antes de entrar al cuerpo, así que, según el valor inicial de la variable de la condición, el bucle puede terminar sin enviar nada.

Un bucle do...while (una sentencia que ejecuta el cuerpo una vez y después comprueba la condición) se escribe do { cuerpo } while (condición);, y todo, hasta el punto y coma final, forma una sola sentencia. Como la comprobación va después del cuerpo, el cuerpo se ejecuta una vez aunque la condición no se cumpla desde el principio.

const attempts = [false, false, true];   // resultados de envío preparados de antemano (true = éxito)
let sent = true;                         // quedó en true por la notificación anterior
let tried = 0;

// while comprueba primero, así que termina sin enviar ni una vez
while (!sent && tried < attempts.length) {
  sent = attempts[tried];
  tried++;
}
console.log(`Envíos con while: ${tried}`);   // Envíos con while: 0

// do...while hace el primer envío antes de comprobar y usa el resultado para decidir si sigue
do {
  sent = attempts[tried];
  tried++;
  console.log(`Intento ${tried}: ${sent ? "correcto" : "fallido"}`);
} while (!sent && tried < attempts.length);
// Intento 1: fallido / Intento 2: fallido / Intento 3: correcto
Cómo empiezan while y do...while
Empieza consent = trueComprueba primero!true es falseNo entraal cuerpoEnviado 0 vecesEmpieza consent = truePrimero el cuerpo:intento 1Resultado false:!false: sigueTermina con éxitoen el intento 3
Los dos bucles empiezan con sent todavía en true. while termina con solo la comprobación, mientras que do...while envía una vez y después decide si sigue.

Solo la primera vuelta se salta la comprobación; a partir de ahí, el bucle se repite solo mientras se cumple la condición, igual que while. Si no quieres que el cuerpo se ejecute ni una vez cuando la condición no se cumple, elige while. Si quieres que se ejecute una vez antes de mirar el resultado, elige do...while.

Asigna a una reserva de sala de reuniones el número de reserva libre más bajo. El array usedNumbers, que contiene los números ya ocupados, ya está declarado.

① Prepara una variable que empiece en 0 para guardar el número que vas a asignar.

② Con un bucle que ejecuta el cuerpo antes de comprobar, aumenta el número en 1 e imprime "Comprobando el número ◯".

③ Escribe una condición que siga repitiendo mientras el número esté en el array de números usados.

④ Después del bucle, imprime "Número de reserva: ◯".

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Saltarse solo una vuelta — cuándo usar continue

Cuando recorres una lista de envíos de arriba abajo, querrás saltarte las líneas sin existencias y pasar a la siguiente. Cuantas más condiciones para saltar añades, más se anidan las llaves de los if, y el código de envío, que es lo que de verdad te interesa, acaba enterrado dentro de ellas.

Con continue (una sentencia que se salta el resto de la vuelta actual y pasa a la siguiente), puedes cortar una vuelta en cuanto se da una condición que quieres saltar. El bucle en sí sigue, así que la siguiente vuelta empieza con normalidad por la comprobación de la condición.

const names = ["Agenda A5", "Lámpara de escritorio", "Hub USB"];
const stocks = [12, 0, 5];   // 0 significa sin existencias
let index = 0;

while (index < names.length) {
  const name = names[index];
  const stock = stocks[index];
  index++;   // se avanza primero para que continue no se lo salte

  // En las líneas sin existencias, sáltate el resto de esta vuelta y pasa a la siguiente
  if (stock === 0) {
    console.log(`${name}: sin existencias, se omite`);
    continue;
  }
  console.log(`${name}: se envían ${stock}`);
}
// Agenda A5: se envían 12
// Lámpara de escritorio: sin existencias, se omite
// Hub USB: se envían 5
Línea procesadastock y comprobaciónResultado de esa vuelta
Línea 1: Agenda A5stock es 12, no 0Imprime "se envían 12"
Línea 2: Lámpara de escritoriostock es 0, así que continueNo se ejecuta el envío
Línea 3: Hub USBstock es 5, no 0Imprime "se envían 5"

continue solo se salta las líneas que hay entre él y el final del cuerpo. También puedes usar continue en el cuerpo de for y for...of, y como la expresión de actualización de los paréntesis de un for está fuera del cuerpo, también se ejecuta en las vueltas que llegan a continue.

continue también se salta tu línea de actualización

Si pones index++ después de continue, index no avanza en la vuelta que se salta. La siguiente vuelta vuelve a leer la misma línea, stock sigue en 0, la condición no cambia y el bucle nunca termina. Actualiza la variable que comprueba la condición antes de continue.

Calcula el promedio de las puntuaciones de las reseñas dejando fuera los valores que no se pueden contar. El array scores ya está declarado.

① Prepara variables que empiecen en 0 para el total y la cantidad.

② Usa for...of para recorrer las puntuaciones una a una.

③ Para 0 (sin valorar) y cualquier valor mayor que 5, imprime "Se excluye ◯" y sáltate el resto de esa vuelta.

④ Suma cada puntuación restante al total, aumenta la cantidad y, después del bucle imprime "Promedio: ◯.◯ (◯ reseñas)".

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Parar en cuanto lo encuentras — adónde te lleva break

Supón que quieres revisar un registro (log) desde arriba y encontrar solo el primer error. Si sigues leyendo hasta el final después de encontrarlo, es trabajo desperdiciado y, según cómo lo escribas, un error posterior puede sobrescribir firstError.

Con break (una sentencia que termina de inmediato el bucle en el que está), puedes salir del bucle en la vuelta en que se cumple la condición. Es la misma sentencia que usaste para salir de un switch en el artículo sobre condicionales. El valor que encuentres lo vas a usar fuera del bucle, así que declara firstError antes del bucle.

const logs = ["INFO Inicio", "WARN Respuesta lenta", "ERROR Pago fallido", "ERROR Reenvío fallido"];
let index = 0;
let firstError = "";

while (index < logs.length) {
  const line = logs[index];
  index++;
  if (line.startsWith("ERROR")) {
    firstError = line;
    break;   // ya se encontró el primero, así que no se revisa el resto
  }
}

console.log(`Primer error: ${firstError}`);   // Primer error: ERROR Pago fallido
console.log(`Líneas revisadas: ${index}`);   // Líneas revisadas: 3
Las llaves de las que sale break
Llaves del while (revisa el registro línea por línea)
  • const line = logs[index] — la línea que se revisa en esta vuelta
  • Después de break, la ejecución sale de las llaves y pasa a la siguiente línea con console.log
Llaves del if (solo las líneas que empiezan por ERROR)
  • firstError = line — guarda la línea encontrada
  • break — sale del while externo, no de estas llaves
  • Las líneas que haya debajo de break nunca se ejecutan
No se ejecutan ni las líneas del cuerpo que hay debajo de break ni las vueltas restantes. La ejecución sigue en la línea que viene después de la llave de cierre del while.

Incluso en la vuelta que llega a break, el index++ escrito antes ya se ejecutó. Por eso index se queda en 3, y el "Líneas revisadas: 3" que se imprime después del bucle coincide con la posición de la línea encontrada, contando desde 1.

En qué se diferencian continue y break
continue cuandostock === 0Vuelve a comprobarindex < 3Pasa a la vueltadel Hub USBImprimese envían 5break al hallarel primer ERRORNo compruebaindex < 4No lee el ERRORde la línea 4Va a la línea queimprime el error
Ninguno de los dos ejecuta el resto de las líneas de esa vuelta. continue vuelve a la comprobación de la condición; break sale del bucle sin comprobar.

Asigna existencias a los pedidos en el orden en que se recibieron, y detente en el primer pedido para el que no alcancen. orderQuantities (la cantidad de cada pedido) y stock (las existencias) ya están declaradas.

① Usa for...of para recorrer una a una las cantidades de los pedidos.

② En una vuelta en la que la cantidad sea mayor que las existencias, imprime "Existencias insuficientes para un pedido de ◯" y termina el bucle.

③ En una vuelta en la que alcancen, resta de las existencias e imprime "Se asignan ◯ (quedan ◯)".

④ Después del bucle, imprime "Existencias restantes: ◯".

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1Si un bucle while empieza con su condición cumplida y el cuerpo nunca cambia la variable que comprueba la condición, ¿qué pasa?

Pregunta 2Si la condición no se cumple desde el principio, ¿cuántas veces se ejecuta el cuerpo de un do...while?

Pregunta 3¿Qué pasa a continuación cuando se ejecuta continue dentro de un bucle?