Condicionales: if, else if, else y switch
Objetivos de aprendizajeAl finalizar esta lección serás capaz de:
- Escribir condicionales con if, else if y else para tomar decisiones en tu código
- Utilizar switch para comparaciones con múltiples opciones
- Combinar condiciones con operadores lógicos (&&, ||, !)
- Aplicar patrones comunes de condicionales en situaciones reales
- Evitar los errores más frecuentes al escribir condicionales
1. La estructura if: tomando decisiones
La programación consiste fundamentalmente en tomar decisiones. "Si el usuario tiene 18 años o más, dejarlo entrar. Si no, mostrar un mensaje de error." Esta capacidad de elegir qué código ejecutar según una condición es lo que hace a los programas inteligentes.
La estructura if es la herramienta más básica y poderosa para tomar decisiones en JavaScript.
Sintaxis básica
if (condicion) {
// Este código se ejecuta SOLO si la condición es true
}
La condición entre paréntesis se evalúa como true o false. Si es true, el bloque de código dentro de las llaves se ejecuta. Si es false, se salta por completo.
const edad = 20;
if (edad >= 18) {
console.log("Sos mayor de edad. Podés entrar.");
}
// Output: "Sos mayor de edad. Podés entrar."
const temperatura = 35;
if (temperatura > 30) {
console.log("Hace mucho calor. Tomá agua.");
console.log(`La temperatura actual es ${temperatura}°C`);
}
if...else: dos caminos
Cuando necesitás ejecutar código alternativo si la condición es false:
const hora = 14;
if (hora < 12) {
console.log("¡Buenos días!");
} else {
console.log("¡Buenas tardes!");
}
// Output: "¡Buenas tardes!"
// Ejemplo práctico: verificar stock
const stock = 0;
if (stock > 0) {
console.log(`Disponible. Quedan ${stock} unidades.`);
} else {
console.log("Producto agotado. Te notificamos cuando vuelva.");
}
if...else if...else: múltiples condiciones
Cuando hay más de dos posibilidades:
const nota = 85;
if (nota >= 90) {
console.log("Calificación: Excelente (A)");
} else if (nota >= 80) {
console.log("Calificación: Muy Bueno (B)");
} else if (nota >= 70) {
console.log("Calificación: Bueno (C)");
} else if (nota >= 60) {
console.log("Calificación: Regular (D)");
} else {
console.log("Calificación: Insuficiente (F)");
}
// Output: "Calificación: Muy Bueno (B)"
Importante: JavaScript evalúa las condiciones de arriba a abajo y ejecuta el PRIMER bloque cuya condición sea true. Después salta al final de toda la estructura.
// ⚠️ Error de principiante: orden incorrecto
const precio = 150;
// ❌ MAL: la primera condición atrapa todo
if (precio > 0) {
console.log("Precio normal");
} else if (precio > 100) {
console.log("Precio alto"); // ¡Nunca se ejecuta!
}
// ✅ BIEN: condiciones de más específica a menos específica
if (precio > 100) {
console.log("Precio alto");
} else if (precio > 0) {
console.log("Precio normal");
}
Combinando condiciones con operadores lógicos
const edad = 25;
const tieneLicencia = true;
const tieneMultas = false;
// AND (&&): TODAS las condiciones deben cumplirse
if (edad >= 18 && tieneLicencia && !tieneMultas) {
console.log("Podés conducir");
}
// OR (||): Al menos UNA condición debe cumplirse
const diaSemana = "sábado";
if (diaSemana === "sábado" || diaSemana === "domingo") {
console.log("¡Es fin de semana!");
}
// Combinaciones complejas
const usuario = { edad: 30, plan: "premium", pais: "AR" };
if ((usuario.plan === "premium" || usuario.plan === "enterprise") && usuario.edad >= 18) {
console.log("Acceso completo habilitado");
}
// NOT (!): Negar una condición
const estaLogueado = false;
if (!estaLogueado) {
console.log("Por favor, iniciá sesión");
}
Condicionales anidados
Podés poner un if dentro de otro, aunque hay que tener cuidado con la legibilidad:
const usuario = { nombre: "Ana", edad: 25, suscripcion: "premium" };
// ❌ Demasiado anidado (difícil de leer)
if (usuario) {
if (usuario.edad >= 18) {
if (usuario.suscripcion === "premium") {
console.log("Acceso completo");
} else {
console.log("Acceso básico");
}
} else {
console.log("Menor de edad");
}
}
// ✅ Guard clauses (retorno temprano - más limpio)
function verificarAcceso(usuario) {
if (!usuario) return "Usuario no válido";
if (usuario.edad < 18) return "Menor de edad";
if (usuario.suscripcion !== "premium") return "Acceso básico";
return "Acceso completo";
}
console.log(verificarAcceso(usuario)); // "Acceso completo"
El patrón de guard clauses (retornos tempranos) es preferido por desarrolladores profesionales porque reduce la anidación y hace el código más legible.
2. La estructura switch: comparaciones múltiples
Cuando necesitás comparar una variable con muchos valores posibles, switch puede ser más limpio que una cadena de else if:
const diaSemana = "miércoles";
switch (diaSemana) {
case "lunes":
console.log("Inicio de semana. ¡Fuerza!");
break;
case "martes":
case "miércoles":
case "jueves":
console.log("Mitad de semana. ¡Seguí así!");
break;
case "viernes":
console.log("¡Viernes! Casi fin de semana.");
break;
case "sábado":
case "domingo":
console.log("¡Fin de semana! A descansar.");
break;
default:
console.log("Día no reconocido");
}
// Output: "Mitad de semana. ¡Seguí así!"
El temido break olvidado (fall-through)
Si olvidás el break, JavaScript sigue ejecutando los siguientes case sin verificar la condición. Esto se llama "fall-through" y es una fuente común de bugs:
const fruta = "manzana";
// ❌ Sin break — fall-through bug
switch (fruta) {
case "manzana":
console.log("Es una manzana"); // Se ejecuta
case "banana":
console.log("Es una banana"); // ¡También se ejecuta!
case "cereza":
console.log("Es una cereza"); // ¡También se ejecuta!
}
// Output:
// "Es una manzana"
// "Es una banana"
// "Es una cereza"
Ejemplo práctico: calculadora de envío
function calcularEnvio(zona, peso) {
let costoBase;
switch (zona) {
case "local":
costoBase = 200;
break;
case "provincial":
costoBase = 500;
break;
case "nacional":
costoBase = 900;
break;
case "internacional":
costoBase = 2500;
break;
default:
return { error: `Zona "${zona}" no reconocida` };
}
// Agregar costo por peso extra (más de 1 kg)
const costoExtra = peso > 1 ? (peso - 1) * 150 : 0;
const total = costoBase + costoExtra;
return {
zona,
peso: `${peso} kg`,
costoBase: `$${costoBase}`,
costoExtra: `$${costoExtra}`,
total: `$${total}`
};
}
console.table(calcularEnvio("nacional", 3));
¿if-else o switch?
| Situación | Usar |
|---|---|
| Comparar UNA variable con valores exactos | switch |
| Evaluar rangos (>, <, >=, <=) | if-else |
| Condiciones complejas con && y || | if-else |
| Muchos valores posibles de un mismo dato | switch |
| 2-3 condiciones simples | if-else |
3. Patrones avanzados de condicionales
El operador ternario como alternativa compacta
Ya lo vimos en el módulo anterior, pero vale profundizar su uso con condicionales:
// En vez de:
let mensaje;
if (edad >= 18) {
mensaje = "Adulto";
} else {
mensaje = "Menor";
}
// Podés escribir:
const mensaje = edad >= 18 ? "Adulto" : "Menor";
// Útil para asignaciones condicionales
const descuento = esMiembroVIP ? 0.20 : 0.05;
const saludo = hora < 12 ? "Buenos días" : hora < 18 ? "Buenas tardes" : "Buenas noches";
// Útil en template literals
console.log(`Tenés ${items} item${items !== 1 ? "s" : ""} en el carrito`);
// Útil en JSX (React)
// <p>{estaLogueado ? "Bienvenido" : "Iniciá sesión"}</p>
Objetos como lookup tables (alternativa elegante a switch)
// En vez de un switch largo:
function obtenerPrecioSwitch(plan) {
switch (plan) {
case "basic": return 9.99;
case "pro": return 19.99;
case "enterprise": return 49.99;
default: return 0;
}
}
// Podés usar un objeto como tabla de búsqueda:
const PRECIOS = {
basic: 9.99,
pro: 19.99,
enterprise: 49.99
};
function obtenerPrecio(plan) {
return PRECIOS[plan] ?? 0; // nullish coalescing para el default
}
console.log(obtenerPrecio("pro")); // 19.99
console.log(obtenerPrecio("ultra")); // 0
// Esto es especialmente útil con funciones:
const ACCIONES = {
crear: () => console.log("Creando..."),
editar: () => console.log("Editando..."),
eliminar: () => console.log("Eliminando..."),
};
const accion = "editar";
(ACCIONES[accion] ?? (() => console.log("Acción no encontrada")))();
Validaciones encadenadas
function validarRegistro(datos) {
const errores = [];
if (!datos.nombre || datos.nombre.trim().length < 2) {
errores.push("El nombre debe tener al menos 2 caracteres");
}
if (!datos.email || !datos.email.includes("@")) {
errores.push("El email no es válido");
}
if (!datos.password || datos.password.length < 8) {
errores.push("La contraseña debe tener al menos 8 caracteres");
}
if (datos.password && !/[A-Z]/.test(datos.password)) {
errores.push("La contraseña debe incluir al menos una mayúscula");
}
if (datos.password && !/[0-9]/.test(datos.password)) {
errores.push("La contraseña debe incluir al menos un número");
}
if (datos.edad !== undefined && (datos.edad < 13 || datos.edad > 120)) {
errores.push("La edad debe estar entre 13 y 120 años");
}
return {
esValido: errores.length === 0,
errores
};
}
// Probar
const resultado = validarRegistro({
nombre: "A",
email: "correo-invalido",
password: "1234",
edad: 10
});
console.log(resultado.esValido); // false
console.table(resultado.errores);
// [
// "El nombre debe tener al menos 2 caracteres",
// "El email no es válido",
// "La contraseña debe tener al menos 8 caracteres",
// "La contraseña debe incluir al menos una mayúscula",
// "La edad debe estar entre 13 y 120 años"
// ]
Errores comunes de principiantes
Usar
=en vez de===en la condición:if (x = 5)es una asignación (siempre true),if (x === 5)es una comparación.Olvidar
breaken switch: Sinbreak, el código "cae" al siguiente case. Usábreaken cada case.Orden incorrecto en else if: Poné las condiciones más específicas primero y las más generales al final.
Condicionales demasiado anidados: Más de 2-3 niveles de anidación es señal de que necesitás refactorizar. Usá guard clauses o funciones auxiliares.
No considerar todos los casos: Siempre incluí un
elseodefaultpara manejar situaciones inesperadas.
Puntos clave de esta lección
if-elsees la estructura fundamental para tomar decisiones — evalúa condiciones de arriba a abajo.else ifpermite encadenar múltiples condiciones — la primera que sea true se ejecuta.switches ideal cuando comparás UNA variable con múltiples valores exactos.- Siempre incluí
breaken cada case del switch para evitar fall-through. - Los guard clauses (retornos tempranos) son más limpios que condicionales anidados.
- Los objetos como lookup tables son una alternativa elegante al switch para mapeos simples.
- Ordená las condiciones de más específica a más general para evitar que condiciones amplias atrapen todo.
Quiz de autoevaluación
1. ¿Qué pasa si olvidás el break en un case de switch?
a) Da un error de sintaxis
b) El código sigue ejecutando los cases siguientes (fall-through)
c) Solo se ejecuta ese case
d) El programa se detiene
2. ¿Cuál es la salida de if (0) { console.log('A') } else { console.log('B') }?
a) A
b) B
c) Error
d) Nada
3. ¿Qué son las guard clauses?
a) Funciones de seguridad
b) Retornos tempranos que evitan anidación excesiva
c) Un tipo de loop
d) Validaciones de HTML
4. ¿Cuándo es preferible usar switch sobre if-else?
a) Siempre
b) Cuando evaluás rangos numéricos
c) Cuando comparás una variable con múltiples valores exactos
d) Cuando hay condiciones complejas con &&
5. ¿Qué operador usamos para negar una condición?
a) &&
b) ||
c) !
d) !!
Respuestas: 1-b, 2-b, 3-b, 4-c, 5-c
Revisemos los puntos más importantes de esta lección antes de continuar.
Ejercicio práctico
Misión: Sistema de descuentos de una tienda online
Creá una función calcularPrecioFinal(producto, usuario) que:
- Reciba un objeto producto con
{ nombre, precio, categoria }y un objeto usuario con{ tipo, edad, esPrimeraCompra } - Aplique descuentos según estas reglas:
- Miembros VIP: 15% de descuento
- Estudiantes (edad < 25): 10% de descuento
- Primera compra: 5% extra
- Si la categoría es "liquidación": 20% adicional
- Los descuentos se acumulan (se aplican uno después del otro)
- Use guard clauses para validar que los datos sean correctos
- Retorne un objeto con el precio original, cada descuento aplicado y el precio final
const producto = { nombre: "Zapatillas Nike", precio: 15000, categoria: "deportes" };
const usuario = { tipo: "vip", edad: 22, esPrimeraCompra: true };
console.log(calcularPrecioFinal(producto, usuario));
- Comprendo el concepto principal y puedo explicarlo con mis palabras
- Entiendo cómo aplicarlo en mi situación específica
- Necesito repasar algunas partes antes de continuar
- Quiero ver más ejemplos prácticos del tema