Estructuras de control
Domina las estructuras de control en JavaScript: condicionales, bucles, switch, ternarios y sus trampas. Aprende cuándo usar cada una y evita errores silenciosos.
Las estructuras de control permiten modificar el flujo de ejecución de un programa. En JavaScript, son fundamentales para tomar decisiones, repetir tareas y construir lógica condicional y repetitiva de forma precisa.
Condicionales
if
/ else
Permite ejecutar un bloque de código u otro según si una condición se evalúa como verdadera o falsa.
const age = 20;
if (age >= 18) {
console.log("You can vote");
} else {
console.log("Too young to vote");
}
else if
Permite encadenar múltiples condiciones y ejecutar diferentes bloques según cuál se cumpla primero.
const score = 85;
if (score >= 90) {
console.log("A grade");
} else if (score >= 80) {
console.log("B grade");
} else {
console.log("Below B");
}
switch
Evalúa un mismo valor contra múltiples posibles casos. Útil para condiciones exactas.
const fruit = "apple";
switch (fruit) {
case "banana":
console.log("Yellow fruit");
break;
case "apple":
console.log("Red or green fruit");
break;
default:
console.log("Unknown fruit");
}
Bucles
while
Ejecuta un bloque de código mientras la condición se mantenga verdadera.
let i = 0;
while (i < 3) {
console.log(i);
i++;
}
do...while
Igual que while
, pero garantiza que el bloque se ejecuta al menos una vez.
let i = 0;
do {
console.log(i);
i++;
} while (i < 3);
for
Bucle con contador. Se ejecuta mientras una condición sea verdadera, con control explícito del índice.
for (let i = 0; i < 3; i++) {
console.log(i);
}
for...of
Itera sobre los valores de un iterable (array
, string
, Set
, Map
).
const colors = ["red", "green", "blue"];
for (const color of colors) {
console.log(color);
}
for...in
Itera sobre las claves (propiedades enumerables) de un objeto.
const user = { name: "Ana", age: 30 };
for (const key in user) {
console.log(`${key}: ${user[key]}`);
}
for...in
vs for...of
Característica | for...in |
for...of |
---|---|---|
Itera | Claves (índices o propiedades) | Valores |
Sirve para | Objetos planos, arrays con propiedades | Arrays , strings , Sets , Maps |
Incluye propiedades heredadas | Sí | No |
Ideal para | Recorrer objetos | Recorrer colecciones |
Nota sobre arrays dispersos (sparse arrays)
const arr = [];
arr[3] = 'x';
Un array disperso tiene huecos (índices no definidos). for...in
recorre los índices definidos, incluso si están vacíos. for...of
ignora esos huecos.
for (const i in arr) {
console.log(i); // 3
}
for (const value of arr) {
console.log(value); // undefined x
}
Operador ternario
Forma corta de un if/else
para asignaciones o evaluaciones simples.
const age = 18;
const result = (age >= 18) ? "Adult" : "Minor";
Evita ternarios anidados o difíciles de leer. Usa if/else
si necesitas claridad o varias condiciones.
break
y continue
break
Rompe completamente la ejecución de un bucle.
for (let i = 0; i < 5; i++) {
if (i === 3) break;
console.log(i);
}
continue
Salta a la siguiente iteración del bucle.
for (let i = 0; i < 5; i++) {
if (i === 2) continue;
console.log(i);
}
Cuándo usar cada uno
for...of
vs forEach
- Usa
for...of
si necesitas cortar la ejecución conbreak
ocontinue
. - Usa
forEach
para transformaciones simples donde no necesitas controlar el flujo.
switch
vs if/else
switch
: cuando comparas un mismo valor contra varios casos fijos.if/else
: cuando necesitas evaluar condiciones complejas o rangos.
Ternario vs if/else
- Usa ternario para condiciones simples y asignaciones directas.
- Evita ternarios con más de dos ramas o con lógica anidada.
- Si necesitas claridad o varias condiciones, usa
if/else
.
Trampas comunes
- Olvidar el
break
en unswitch
: provoca ejecuciones encadenadas. - Usar
==
en vez de===
: puede dar resultados inesperados (coercion). - Bucles infinitos por olvidar incrementar la variable de control.
- Recorrer un array con
for...in
: puede incluir propiedades añadidas manualmente. - Modificar un array mientras lo recorres con
for
: puede romper los índices.
Enlaces útiles
Desafío Práctico: Estructuras de control JavaScript
Prueba a resolver este desafío antes de continuar
Trabajas en una startup de videojuegos y tu jefe necesita un sistema básico para analizar las puntuaciones de los jugadores. El juego acaba de lanzarse y están llegando miles de puntuaciones cada día.
El equipo de producto quiere entender cómo está funcionando el juego:
- ¿Cuántos jugadores están en cada nivel de habilidad?.
- ¿Qué tan rápido pueden encontrar jugadores "pro" para torneos?.
- ¿Cuál es la puntuación máxima actual?.
- ¿Cuántas partidas necesita un jugador promedio para llegar a cierto puntaje?.
Tu tarea es crear 5 funciones simples que respondan estas preguntas. Las puntuaciones van de 0 a 100 puntos.
// Example: array of player scores
const scores = [45, 78, 92, 23, 67, 88, 34, 56, 91];
// Your functions should do this:
countByLevel(scores); // { high: 3, medium: 3, low: 3 }
findFirstAbove(scores, 80); // 92 (first score >= 80)
getScoreLevel(78); // "medium"
calculateStat(scores, "max"); // 92
addUntilTarget(scores, 200); // 3 (added 45+78+92 = 215)
Tu Código
Solución
Paso 1: Contar por Nivel (for...of + if/else if)
function countByLevel(scores) {
const levels = { high: 0, medium: 0, low: 0 };
for (const score of scores) {
if (score >= 80) {
levels.high++;
} else if (score >= 50) {
levels.medium++;
} else {
levels.low++;
}
}
return levels;
}
Por qué if/else if: Cada puntuación va en exactamente una categoría.
Paso 2: Buscar Primera Puntuación Alta (for...of + return + continue)
function findFirstAbove(scores, target) {
for (const score of scores) {
// Skip invalid scores
if (score < 0) continue;
if (score >= target) {
return score; // Found it - stop searching
}
}
return -1; // Not found
}
Por qué continue: Saltamos puntuaciones inválidas sin anidar más ifs. Por qué return: Para el bucle inmediatamente cuando encontramos coincidencia.
Paso 3: Clasificar Puntuación Individual (if/else if)
function getScoreLevel(score) {
if (score >= 80) {
return "high";
} else if (score >= 50) {
return "medium";
} else {
return "low";
}
}
Paso 4: Calcular Estadísticas (switch)
function calculateStat(scores, stat) {
switch (stat) {
case "max":
let max = scores[0];
for (const score of scores) {
if (score > max) {
max = score;
}
}
return max;
case "sum":
let total = 0;
for (const score of scores) {
total += score;
}
return total;
case "count":
return scores.length;
default:
return 0;
}
}
Por qué switch: 3 operaciones específicas, más claro que if/else if.
Paso 5: Sumar Hasta Objetivo (while)
function addUntilTarget(scores, target) {
let total = 0;
let count = 0;
let index = 0;
while (index < scores.length && total < target) {
total += scores[index];
count++;
index++;
}
return count;
}
Por qué while: No sabemos cuántas puntuaciones necesitamos sumar para alcanzar el objetivo.
Solución Completa
const gameScores = [45, 78, 92, 23, 67, 88, 34, 56, 91];
function countByLevel(scores) {
const levels = { high: 0, medium: 0, low: 0 };
for (const score of scores) {
if (score >= 80) {
levels.high++;
} else if (score >= 50) {
levels.medium++;
} else {
levels.low++;
}
}
return levels;
}
function findFirstAbove(scores, target) {
for (const score of scores) {
if (score < 0) continue;
if (score >= target) {
return score;
}
}
return -1;
}
function getScoreLevel(score) {
if (score >= 80) {
return "high";
} else if (score >= 50) {
return "medium";
} else {
return "low";
}
}
function calculateStat(scores, stat) {
switch (stat) {
case "max":
let max = scores[0];
for (const score of scores) {
if (score > max) {
max = score;
}
}
return max;
case "sum":
let total = 0;
for (const score of scores) {
total += score;
}
return total;
case "count":
return scores.length;
default:
return 0;
}
}
function addUntilTarget(scores, target) {
let total = 0;
let count = 0;
let index = 0;
while (index < scores.length && total < target) {
total += scores[index];
count++;
index++;
}
return count;
}