JavaScript
Bucles
Compara for, while, do...while, for...of y for...in para repetir tareas, recorrer colecciones y evitar límites o bucles infinitos.
- Última actualización
- Actualizada
- Nivel
- Fundamentos
- Fundamentos de programación
JavaScript
Compara for, while, do...while, for...of y for...in para repetir tareas, recorrer colecciones y evitar límites o bucles infinitos.
Un bucle repite un bloque de código. La repetición puede depender de un contador, una condición o los elementos de una colección.
for (const product of products) {
console.log(product.name);
}Todo bucle necesita responder, de alguna forma, tres preguntas:
let count = 0;
while (count < 3) {
console.log(count);
count++;
}count = 0.count < 3.count aumenta.Si ninguna parte acerca el bucle a su final, puede convertirse en un bucle infinito.
for reúne la inicialización, la condición y la actualización en una sola estructura.
for (let index = 0; index < 3; index++) {
console.log(index);
}Su forma general es:
for (initialization; condition; update) {
// Bloque repetido.
}El orden de ejecución es:
const products = ["Keyboard", "Mouse", "Monitor"];
for (let index = 0; index < products.length; index++) {
console.log(index, products[index]);
}El índice es útil cuando necesitas:
Este bucle intenta acceder a una posición que no existe:
for (let index = 0; index <= products.length; index++) {
console.log(products[index]);
}El último índice válido es length - 1. Por eso la condición habitual es:
index < products.length;Los errores donde falta o sobra una iteración suelen llamarse off-by-one errors.
while repite un bloque mientras una condición sea truthy.
while (hasPendingTasks()) {
processNextTask();
}Es útil cuando no conoces de antemano la cantidad exacta de repeticiones.
let attempts = 0;
let connected = false;
while (!connected && attempts < 3) {
connected = tryConnection();
attempts++;
}La condición se comprueba antes de cada vuelta. Si comienza siendo falsy, el bloque no se ejecuta.
let stock = 0;
while (stock > 0) {
stock--;
}Aquí no ocurre ninguna iteración.
do...while ejecuta primero el bloque y comprueba la condición después.
let option;
do {
option = readMenuOption();
} while (!isValidOption(option));Por eso garantiza al menos una ejecución.
let count = 10;
do {
console.log(count);
} while (count < 5);Aunque la condición es falsa, imprime 10 una vez.
do...while es menos frecuente, pero resulta natural cuando la primera ejecución debe ocurrir antes de saber si hay que repetir.
for...of recorre los valores de un iterable.
const products = ["Keyboard", "Mouse", "Monitor"];
for (const product of products) {
console.log(product);
}Es una opción clara cuando necesitas trabajar con cada elemento y no necesitas controlar manualmente el índice.
También funciona con strings:
for (const character of "JavaScript") {
console.log(character);
}Y con otras estructuras iterables como Set, Map y generadores, que se estudiarán más adelante.
for (const [index, product] of products.entries()) {
console.log(index, product);
}for...in recorre nombres de propiedades enumerables.
const user = {
name: "Nicolás",
role: "developer",
};
for (const key in user) {
console.log(key, user[key]);
}No es la opción recomendada para arrays:
for (const index in products) {
console.log(index); // Los índices llegan como strings.
}Además, for...in puede incluir propiedades heredadas. Cuando necesitas únicamente propiedades propias, suelen ser más explícitos:
Object.keys(user);
Object.values(user);
Object.entries(user);for (const [key, value] of Object.entries(user)) {
console.log(key, value);
}| Necesidad | Opción habitual |
|---|---|
| Controlar índice, inicio o saltos | `for` |
| Repetir mientras exista una condición | `while` |
| Ejecutar al menos una vez | `do...while` |
| Recorrer valores de una colección | `for...of` |
| Recorrer claves enumerables | `for...in` o `Object.entries` |
No se trata de escoger la sintaxis más corta, sino la que comunica mejor por qué existe la repetición.
Los arrays ofrecen métodos como map, filter, find, some, every, reduce y forEach.
const activeProducts = products.filter(
(product) => product.isActive,
);Estos métodos suelen expresar mejor una transformación o búsqueda concreta.
Un bucle resulta útil cuando necesitas:
break o continue.for (const product of products) {
if (product.id === targetId) {
selectedProduct = product;
break;
}
}Para una búsqueda simple, find sería más declarativo:
const selectedProduct = products.find(
(product) => product.id === targetId,
);Ambos son válidos. La intención del código debe guiar la elección.
Este bucle nunca modifica count:
let count = 0;
while (count < 3) {
console.log(count);
}La condición permanece siempre verdadera.
Un bucle infinito también puede ser intencional:
while (true) {
const message = readNextMessage();
if (message === null) {
break;
}
processMessage(message);
}En ese caso debe existir una salida clara.
Eliminar elementos de un array mientras avanzas hacia delante puede saltar posiciones.
const numbers = [1, 2, 3, 4];
for (let index = 0; index < numbers.length; index++) {
if (numbers[index] % 2 === 0) {
numbers.splice(index, 1);
}
}Cuando se elimina 2, el 3 cambia de posición y el índice continúa avanzando.
Para obtener una colección sin ciertos elementos, suele ser más claro crear una nueva:
const oddNumbers = numbers.filter(
(number) => number % 2 !== 0,
);Si necesitas modificar el array original, recorrer desde el final evita el desplazamiento de índices pendientes:
for (let index = numbers.length - 1; index >= 0; index--) {
if (numbers[index] % 2 === 0) {
numbers.splice(index, 1);
}
}function inspectInventory(products) {
const report = {
inactive: [],
outOfStock: [],
lowStock: [],
};
for (const product of products) {
if (!product.isActive) {
report.inactive.push(product.id);
continue;
}
if (product.stock === 0) {
report.outOfStock.push(product.id);
continue;
}
if (product.stock <= product.minimumStock) {
report.lowStock.push(product.id);
}
}
return report;
}for...of comunica que se procesará cada producto. continue evita anidar las condiciones y pasa al siguiente elemento cuando el caso actual ya fue clasificado.
<= array.length y recorrer una posición inexistente.for...in para arrays sin entender sus diferencias.forEach cuando se necesita detener la iteración.for ofrece control explícito de inicio, condición y actualización.while comprueba la condición antes de cada vuelta.do...while ejecuta el bloque al menos una vez.for...of recorre valores de iterables.for...in recorre nombres de propiedades enumerables.¿Qué valores imprime este bucle?
const values = [10, 20, 30];
for (let index = 0; index <= values.length; index++) {
console.log(values[index]);
}10
20
30
undefinedLa condición permite index === values.length, pero esa posición no existe. Debe utilizarse index < values.length.
break y continue explica cómo detener un bucle o saltar directamente a su siguiente iteración.