Unidad 11 · Lecciones 080-087
Iteradores en JavaScript
Una estructura de control decide si se ejecuta un codigo. Un iterador decide cuantas veces. Mostrar los comentarios de una publicacion, listar los productos del carrito, recorrer los tweets que te perdiste: todo eso es repetir codigo hasta que ya no quede nada que mostrar.
🎯 Objetivo de aprendizaje
Al terminar conoceras los seis iteradores del lenguaje, sabras cual usar en cada situacion,
podras cortar o saltar vueltas con break y continue, y habras resuelto
el ejercicio FizzBuzz.
11.1 El for loop
El iterador clasico, presente en casi todos los lenguajes con una sintaxis muy parecida. Lo usaste en la Unidad 8; aqui lo analizamos a fondo.
for (let i = 0; i < 10; i++) {
console.log(`Numero: ${i}`);
}
| # | Parte | Codigo | Funcion |
|---|---|---|---|
| 1 | Inicializador | let i = 0 | Desde donde empieza a contar. |
| 2 | Condicion | i < 10 | Mientras se cumpla, sigue repitiendo. |
| 3 | Incremento | i++ | Como avanza en cada vuelta. |
💡 Por que se llama i
Por convencion: viene de indice. No le pongas indice ni contador;
en cualquier equipo del mundo se espera ver i.
El bucle anterior imprime del 0 al 9. Al llegar a 10, la condicion 10 < 10 ya no se cumple y se detiene.
// De dos en dos
for (let i = 0; i < 10; i += 2) {
console.log(i);
}
console.log('---');
// Llegar hasta el 10 incluido
for (let i = 0; i <= 10; i++) {
console.log(i);
}
11.2 Ejercicio clasico: pares e impares
🎓 Pregunta habitual para perfiles junior
¿Como identificas los numeros pares y los impares dentro de un bucle? Con el modulo que aprendiste en la Unidad 4: todo numero divisible entre 2 con residuo 0 es par.
for (let i = 1; i < 20; i++) {
if (i % 2 === 0) {
console.log(`El numero ${i} es par`);
} else {
console.log(`El numero ${i} es impar`);
}
}
Fijate en como se combinan tres unidades distintas: el bucle (11), el condicional (10) y el operador modulo (4). A partir de aqui casi todo el codigo mezcla varios conceptos.
11.3 break y continue
- break
- Rompe el bucle entero. Sale inmediatamente, aunque la condicion siguiera cumpliendose.
- continue
- Salta solo la vuelta actual. No ejecuta el resto del cuerpo, pero el bucle continua.
for (let i = 0; i < 10; i++) {
if (i === 5) {
console.log('Este es el 5');
break;
}
console.log(`Numero: ${i}`);
}
for (let i = 0; i < 10; i++) {
if (i === 5) {
console.log('Cinco');
continue;
}
console.log(`Numero: ${i}`);
}
Un uso real de continue
Marcar el producto del carrito que tenga descuento, sin que se imprima dos veces:
const carrito = [
{ nombre: 'Monitor 27 pulgadas', precio: 500 },
{ nombre: 'Tablet', precio: 100, descuento: true },
{ nombre: 'Celular', precio: 800 }
];
for (let i = 0; i < carrito.length; i++) {
if (carrito[i].descuento) {
console.log(`El articulo ${carrito[i].nombre} tiene descuento`);
continue; // ya lo mostramos, saltamos a la siguiente vuelta
}
console.log(carrito[i].nombre);
}
💡 Fijate en el if
Se escribe if (carrito[i].descuento), no === true. Es exactamente la
buena practica de la Unidad 6.
11.4 Actividad integradora: FizzBuzz
🎯 El enunciado
Recorre los numeros del 1 al 100 y, para cada uno:
- Si es multiplo de 3 → imprime
Fizz - Si es multiplo de 5 → imprime
Buzz - Si es multiplo de 3 y de 5 → imprime
FizzBuzz
Es el ejercicio de entrevista mas famoso del mundo y mucha gente lo suspende. No por dificil, sino por un detalle de orden. Vamos paso a paso, que es la forma correcta de atacar cualquier problema que no sepas resolver de golpe.
Paso 1: generar los numeros
for (let i = 1; i <= 20; i++) {
console.log(i);
}
Paso 2: detectar los multiplos de 3
for (let i = 1; i <= 20; i++) {
if (i % 3 === 0) {
console.log('Fizz');
} else {
console.log(i);
}
}
Paso 3: anadir los multiplos de 5
for (let i = 1; i <= 20; i++) {
if (i % 3 === 0) {
console.log('Fizz');
} else if (i % 5 === 0) {
console.log('Buzz');
} else {
console.log(i);
}
}
✗ Aqui es donde falla casi todo el mundo
El 15 imprime Fizz en lugar de FizzBuzz. ¿Por que? Porque
un if ejecuta solo la primera condicion que se cumple (Unidad 10),
y 15 es multiplo de 3, asi que entra ahi y nunca llega a comprobar nada mas.
Anadir un tercer else if al final tampoco lo arregla, por el mismo
motivo.
Paso 4: la solucion
La condicion de FizzBuzz es la menos frecuente de las tres, asi que tiene que ir primero:
for (let i = 1; i <= 30; i++) {
if (i % 15 === 0) {
console.log('FizzBuzz');
} else if (i % 3 === 0) {
console.log('Fizz');
} else if (i % 5 === 0) {
console.log('Buzz');
} else {
console.log(i);
}
}
Ver una solucion alternativa (sin el 15)
En programacion casi siempre hay varias formas de resolver lo mismo. Esta usa &&:
for (let i = 1; i <= 30; i++) {
if (i % 3 === 0 && i % 5 === 0) {
console.log('FizzBuzz');
} else if (i % 3 === 0) {
console.log('Fizz');
} else if (i % 5 === 0) {
console.log('Buzz');
} else {
console.log(i);
}
}
Es equivalente: un numero divisible entre 3 y entre 5 es exactamente un multiplo de 15. Esta version es un poco mas explicita sobre la intencion.
✓ La leccion de fondo
Cuando un problema te supera, divide y avanza por pasos: primero los numeros, luego una condicion, luego la otra, y al final el caso especial. Esa es la habilidad que realmente se evalua en una entrevista.
11.5 while
Tiene las mismas tres partes que el for, pero repartidas en tres lugares distintos.
Se ejecuta mientras la condicion sea verdadera.
let i = 0; // 1. inicializador, FUERA del bucle
while (i < 10) { // 2. condicion, en el parentesis
console.log(`Numero ${i}`);
i++; // 3. incremento, al final del cuerpo
}
✗ El peligro del while
Si olvidas el incremento, el bucle no termina nunca y bloquea el navegador.
Es el error mas comun con while. El for lo evita porque el incremento
forma parte de su propia sintaxis.
let i = 100;
while (i < 10) {
console.log(`Numero ${i}`);
i++;
}
console.log('El while no imprimio nada');
11.6 do while
Igual que el while, con una diferencia importante: se ejecuta al menos una
vez, porque comprueba la condicion despues de ejecutar el cuerpo.
let i = 0;
do {
console.log(`Numero ${i}`);
i++;
} while (i < 10);
let i = 1000; // la condicion NO se cumple desde el principio
do {
console.log(`Numero ${i}`); // aun asi, se ejecuta una vez
i++;
} while (i < 10);
🎓 Pregunta de entrevista
¿Cual es la diferencia entre while y do while?
while comprueba la condicion antes, asi que puede no ejecutarse ni
una sola vez. do while la comprueba despues, por lo que su cuerpo
se ejecuta siempre al menos una vez.
11.7 forEach y map: los iteradores de JavaScript
for, while y do while existen en casi todos los lenguajes.
Pero JavaScript tiene los suyos propios, pensados especificamente para arreglos, y son los que
mas usaras.
const pendientes = ['Tarea', 'Comer', 'Proyecto', 'Estudiar JavaScript'];
pendientes.forEach(pendiente => console.log(pendiente));
El segundo parametro: el indice
const pendientes = ['Tarea', 'Comer', 'Proyecto', 'Estudiar JavaScript'];
pendientes.forEach((pendiente, index) => {
console.log(`${index}: ${pendiente}`);
});
💡 Los nombres los eliges tu
pendiente e index son nombres inventados por ti. Lo que importa es el
orden: el primer parametro es siempre el elemento y el segundo siempre el indice.
La diferencia con map, otra vez
const carrito = [
{ nombre: 'Monitor 27 pulgadas', precio: 500 },
{ nombre: 'Tablet', precio: 100 }
];
const nuevoArreglo = carrito.map(producto => `${producto.nombre} - ${producto.precio}`);
const nuevoArreglo2 = carrito.forEach(producto => `${producto.nombre} - ${producto.precio}`);
console.log(nuevoArreglo); // el arreglo con los textos
console.log(nuevoArreglo2); // undefined
11.8 for...of: la version simplificada
Recorre un arreglo sin contadores, sin length y sin indices. Es la forma mas legible
de recorrer un arreglo de principio a fin.
const pendientes = ['Tarea', 'Comer', 'Proyecto', 'Estudiar JavaScript'];
for (let pendiente of pendientes) {
console.log(pendiente);
}
Como leerlo
«Para cada pendiente de pendientes».
En cada vuelta, la variable que tu nombras recibe el elemento actual. Cuando el arreglo se acaba,
el bucle se detiene solo.
const carrito = [
{ nombre: 'Monitor 27 pulgadas', precio: 500 },
{ nombre: 'Tablet', precio: 100 },
{ nombre: 'Celular', precio: 800 }
];
for (let producto of carrito) {
console.log(`${producto.nombre}: ${producto.precio}`);
}
Compara con el for equivalente de la Unidad 8: mismo resultado, mitad de ruido.
11.9 for...in: recorrer objetos
⚠ La confusion mas comun
for...of y for...in se escriben casi igual, pero no hacen lo mismo:
for...of recorre arreglos; for...in recorre objetos.
const pendientes = ['Tarea', 'Comer', 'Proyecto'];
for (let pendiente in pendientes) {
console.log(pendiente); // 0, 1, 2 <-- las posiciones, no los valores
}
const automovil = {
modelo: 'Camaro',
year: 1969,
motor: '6.0'
};
// Las LLAVES del objeto
for (let propiedad in automovil) {
console.log(propiedad);
}
console.log('--- ahora los valores ---');
// Los VALORES: se accede con corchetes, porque el nombre esta en una variable
for (let propiedad in automovil) {
console.log(`${propiedad}: ${automovil[propiedad]}`);
}
💡 Aqui aparece la sintaxis de corchetes
En la Unidad 7 viste que se podia acceder con
objeto['llave']. Este es el caso donde es imprescindible: el nombre
de la propiedad esta dentro de una variable, asi que automovil.propiedad buscaria
una llave llamada literalmente "propiedad" y no funcionaria.
La alternativa moderna: Object.entries()
Desde ECMAScript 2017 hay una forma mas comoda de recorrer un objeto: convertirlo en pares
[llave, valor] y recorrerlos con for...of y destructuring de arreglos.
const automovil = {
modelo: 'Camaro',
year: 1969,
motor: '6.0'
};
for (let [llave, valor] of Object.entries(automovil)) {
console.log(`${llave} -> ${valor}`);
}
Aqui se combinan tres cosas que ya conoces: Object.entries() (Unidad 7),
el destructuring de arreglos (Unidad 8) y for...of (seccion anterior).
11.10 ¿Cual uso en cada caso?
| Iterador | Recorre | Usalo cuando |
|---|---|---|
for | Cualquier cosa contable | Necesitas control total del contador o saltar de N en N. |
while | Hasta que algo deje de cumplirse | No sabes de antemano cuantas vueltas daras. |
do while | Igual que while | El cuerpo debe ejecutarse al menos una vez si o si. |
forEach | Arreglos | Solo quieres hacer algo con cada elemento. |
map | Arreglos | Quieres transformar el arreglo en uno nuevo. |
for...of | Arreglos | Quieres la sintaxis mas limpia y no necesitas el indice. |
for...in | Objetos | Necesitas recorrer las propiedades de un objeto. |
💡 En la practica
En codigo JavaScript moderno veras sobre todo forEach, map y
for...of. El for clasico sigue siendo util, y while /
do while aparecen menos, pero se preguntan en entrevistas.
11.11 Ejercicios practicos
Pares e impares con while
Reescribe el ejercicio de pares e impares de la seccion 11.2 usando un while
en lugar de un for.
Este ejercicio se propone explicitamente en el material original del curso.
Ver solucion
let i = 1;
while (i < 20) {
if (i % 2 === 0) {
console.log(`El numero ${i} es par`);
} else {
console.log(`El numero ${i} es impar`);
}
i++; // sin esta linea el bucle no termina nunca
}
Total del carrito
Recorre un carrito de cuatro productos y calcula el total a pagar. Hazlo dos veces:
con for...of y con forEach.
Ver solucion
const carrito = [
{ nombre: 'Monitor', precio: 500 },
{ nombre: 'Tablet', precio: 100 },
{ nombre: 'Celular', precio: 800 },
{ nombre: 'Teclado', precio: 50 }
];
// Con for...of
let total1 = 0;
for (let producto of carrito) {
total1 += producto.precio;
}
console.log('Total con for...of:', total1);
// Con forEach
let total2 = 0;
carrito.forEach(producto => total2 += producto.precio);
console.log('Total con forEach:', total2);
En la Unidad 12 veras que existe un metodo,
reduce, disenado exactamente para esto.
Buscar y parar
Recorre un arreglo de usuarios buscando uno concreto por su email. En cuanto lo encuentres, muestralo y detén el bucle para no seguir recorriendo innecesariamente.
Ver solucion
const usuarios = [
{ nombre: 'Ana', email: 'ana@correo.com' },
{ nombre: 'Luis', email: 'luis@correo.com' },
{ nombre: 'Marta', email: 'marta@correo.com' },
{ nombre: 'Pedro', email: 'pedro@correo.com' }
];
const buscado = 'marta@correo.com';
for (let i = 0; i < usuarios.length; i++) {
console.log(`Revisando la posicion ${i}...`);
if (usuarios[i].email === buscado) {
console.log(`Encontrado: ${usuarios[i].nombre} en la posicion ${i}`);
break; // no seguimos: ya lo tenemos
}
}
Sin break, el bucle revisaria tambien a Pedro sin necesidad. Con arreglos
pequenos da igual, pero con miles de registros importa.
FizzBuzz con while
Resuelve FizzBuzz otra vez, pero usando un while en vez de un for.
Comprueba que el resultado es identico.
Ver solucion
let i = 1;
while (i <= 30) {
if (i % 15 === 0) {
console.log('FizzBuzz');
} else if (i % 3 === 0) {
console.log('Fizz');
} else if (i % 5 === 0) {
console.log('Buzz');
} else {
console.log(i);
}
i++;
}
La logica de las condiciones es exactamente la misma: lo unico que cambia es el mecanismo de repeticion. Cualquier iterador sirve para resolver cualquier problema de este tipo.
11.12 Resumen de lo aprendido
- Un iterador repite codigo hasta que una condicion deja de cumplirse.
fortiene tres partes: inicializador, condicion e incremento, todas en el parentesis.breakrompe el bucle entero;continuesalta solo la vuelta actual.- FizzBuzz se resuelve poniendo la condicion menos frecuente primero, porque un
ifsolo ejecuta la primera que se cumple. whilereparte las tres partes; si olvidas el incremento, bucle infinito.do whileejecuta el cuerpo al menos una vez, porque comprueba la condicion al final.forEachrecorre arreglos y te pasa el elemento y (opcionalmente) el indice.maphace lo mismo pero devuelve un arreglo nuevo.for...ofrecorre arreglos sin contadores.for...inrecorre objetos, y sus valores se leen con corchetes.Object.entries()+for...of+ destructuring es la forma moderna de recorrer un objeto.
11.13 Verificacion de cierre
En FizzBuzz, ¿por que hay que comprobar primero los multiplos de 15?
- Porque 15 es mayor que 3 y que 5
- Porque el modulo de 15 es mas rapido de calcular
- Porque el
ifsolo ejecuta la primera condicion que se cumple - No hace falta: el orden da igual
¿Cual es la diferencia entre while y do while?
do whilese ejecuta al menos una vez aunque la condicion no se cumplado whilesolo funciona con arregloswhilees mas rapido- Ninguna: es la misma sintaxis escrita al reves
¿Que devuelve for (let x in ['a','b','c']) en cada vuelta?
- Los valores
'a','b','c' - El arreglo completo tres veces
- Un error, porque
for...inno admite arreglos - Los indices
0,1,2
🏁 Unidad completada