Ir al contenido principal

Switch case

Introducción

La estructura switch es una alternativa a múltiples declaraciones if/else cuando necesitamos comparar una variable con diferentes valores. Esta estructura de control nos permite evaluar una expresión contra varios casos posibles y ejecutar el bloque de código correspondiente al caso que coincida. El switch case resulta especialmente útil cuando tenemos múltiples condiciones basadas en el valor de una misma variable, haciendo que nuestro código sea más organizado, legible y, en algunos casos, más eficiente.

Sintaxis de la estructura switch

La sintaxis básica de la estructura switch es la siguiente:

switch (expresion) {
    case valor1:
        // Código a ejecutar si expresion === valor1
        break;
    case valor2:
        // Código a ejecutar si expresion === valor2
        break;
    // Más casos según sea necesario
    default:
        // Código a ejecutar si ninguno de los casos coincide
}

Los elementos principales de esta estructura son:

  • expresion: La variable o expresión que se va a evaluar
  • case valorN: Cada uno de los posibles valores que puede tener la expresión
  • break: Sentencia que termina la ejecución del bloque switch
  • default: Bloque opcional que se ejecuta si ningún caso coincide

Veamos un ejemplo básico:

const diaSemana = 3;
let nombreDia;

switch (diaSemana) {
    case 1:
        nombreDia = "Lunes";
        break;
    case 2:
        nombreDia = "Martes";
        break;
    case 3:
        nombreDia = "Miércoles";
        break;
    case 4:
        nombreDia = "Jueves";
        break;
    case 5:
        nombreDia = "Viernes";
        break;
    case 6:
        nombreDia = "Sábado";
        break;
    case 7:
        nombreDia = "Domingo";
        break;
    default:
        nombreDia = "Día no válido";
}

console.log(nombreDia); // Muestra: "Miércoles"

En este ejemplo:

  1. Evaluamos el valor de diaSemana (que es 3)
  2. Recorremos los casos hasta encontrar case 3:
  3. Ejecutamos el código asociado, asignando "Miércoles" a la variable nombreDia
  4. La sentencia break nos saca de la estructura switch

Comparación con múltiples if/else

Para entender mejor el valor de switch, veamos el mismo ejemplo implementado con múltiples condiciones if/else:

const diaSemana = 3;
let nombreDia;

if (diaSemana === 1) {
    nombreDia = "Lunes";
} else if (diaSemana === 2) {
    nombreDia = "Martes";
} else if (diaSemana === 3) {
    nombreDia = "Miércoles";
} else if (diaSemana === 4) {
    nombreDia = "Jueves";
} else if (diaSemana === 5) {
    nombreDia = "Viernes";
} else if (diaSemana === 6) {
    nombreDia = "Sábado";
} else if (diaSemana === 7) {
    nombreDia = "Domingo";
} else {
    nombreDia = "Día no válido";
}

console.log(nombreDia); // Muestra: "Miércoles"

Como podemos observar, la versión con switch resulta más clara y estructurada, especialmente cuando tenemos muchos casos posibles basados en un mismo valor.

Cláusulas case y default

Cláusula case

Cada case representa un valor posible de la expresión evaluada:

  • JavaScript utiliza comparación estricta (===) entre la expresión y el valor del caso
  • Después de cada caso, se escribe el código a ejecutar cuando hay coincidencia
  • El break es fundamental para salir del switch una vez ejecutado el código del caso

Cláusula default

La cláusula default funciona de manera similar al else en las estructuras condicionales:

const fruta = "Mango";
let mensaje;

switch (fruta) {
    case "Manzana":
        mensaje = "Las manzanas son rojas o verdes";
        break;
    case "Plátano":
        mensaje = "Los plátanos son amarillos";
        break;
    case "Naranja":
        mensaje = "Las naranjas son anaranjadas";
        break;
    default:
        mensaje = "No conozco el color de esa fruta";
}

console.log(mensaje); // Muestra: "No conozco el color de esa fruta"

En este ejemplo, como ninguno de los casos coincide con "Mango", se ejecuta el código dentro de default.

Comportamiento del break

La sentencia break es crucial en la estructura switch, ya que determina si la ejecución continúa o se detiene:

const opcion = 2;
let resultado = "";

switch (opcion) {
    case 1:
        resultado += "Opción 1 seleccionada. ";
        // Sin break, continúa ejecutando el siguiente caso
    case 2:
        resultado += "Opción 2 seleccionada. ";
        // Sin break, continúa ejecutando el siguiente caso
    case 3:
        resultado += "Opción 3 seleccionada. ";
        break; // Aquí sí hay break, por lo que detiene la ejecución
    case 4:
        resultado += "Opción 4 seleccionada. ";
        break;
    default:
        resultado += "Opción no válida.";
}

console.log(resultado); 
// Muestra: "Opción 2 seleccionada. Opción 3 seleccionada. "

En este ejemplo:

  1. La expresión coincide con case 2:
  2. Como no hay break después del caso 2, la ejecución continúa al caso siguiente
  3. Se ejecuta también el código del caso 3
  4. El break en el caso 3 detiene la ejecución, por lo que no se llega al caso 4

Este comportamiento se conoce como "fall-through" (ejecución en cascada).

Agrupación de casos

Una característica útil del switch es la posibilidad de agrupar varios casos que comparten el mismo código:

const diaSemana = 5; // Viernes
let tipoDeJornada;

switch (diaSemana) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        tipoDeJornada = "Día laborable";
        break;
    case 6:
    case 7:
        tipoDeJornada = "Fin de semana";
        break;
    default:
        tipoDeJornada = "Día no válido";
}

console.log(tipoDeJornada); // Muestra: "Día laborable"

En este ejemplo, los casos del 1 al 5 comparten el mismo código, al igual que los casos 6 y 7. Esta agrupación hace que el código sea más compacto y evita repeticiones innecesarias.

Fall-through (ejecución en cascada)

El "fall-through" o ejecución en cascada ocurre cuando omitimos intencionalmente la sentencia break para que se ejecuten varios casos consecutivos:

const nivel = 2;
let mensaje = "Tu nivel te permite: ";

switch (nivel) {
    case 3:
        mensaje += "administrar usuarios, ";
        // Cae al caso 2
    case 2:
        mensaje += "crear contenido, ";
        // Cae al caso 1
    case 1:
        mensaje += "leer artículos.";
        break;
    default:
        mensaje = "No tienes permisos.";
}

console.log(mensaje); 
// Muestra: "Tu nivel te permite: crear contenido, leer artículos."

Este patrón es útil cuando queremos que los niveles superiores hereden las capacidades de los niveles inferiores, como en un sistema de permisos.

Casos de uso apropiados

El switch es particularmente útil en los siguientes escenarios:

1. Menús de opciones

function procesarOpcion(opcion) {
    switch (opcion) {
        case "nuevo":
            return "Creando nuevo archivo...";
        case "abrir":
            return "Abriendo archivo existente...";
        case "guardar":
            return "Guardando cambios...";
        case "exportar":
            return "Exportando archivo...";
        case "salir":
            return "Cerrando programa...";
        default:
            return "Opción no reconocida.";
    }
}

console.log(procesarOpcion("guardar")); // Muestra: "Guardando cambios..."

2. Estados de un proceso

const estadoPedido = "enviado";
let mensaje;

switch (estadoPedido.toLowerCase()) {
    case "procesando":
        mensaje = "Tu pedido está siendo preparado.";
        break;
    case "enviado":
        mensaje = "Tu pedido está en camino.";
        break;
    case "entregado":
        mensaje = "Tu pedido ha sido entregado.";
        break;
    case "cancelado":
        mensaje = "Tu pedido ha sido cancelado.";
        break;
    default:
        mensaje = "Estado del pedido desconocido.";
}

console.log(mensaje); // Muestra: "Tu pedido está en camino."

3. Cálculos basados en categorías

function calcularImpuesto(producto, precio) {
    let porcentaje;
    
    switch (producto) {
        case "alimento":
            porcentaje = 4;
            break;
        case "medicamento":
            porcentaje = 4;
            break;
        case "libro":
            porcentaje = 4;
            break;
        case "ropa":
            porcentaje = 21;
            break;
        case "electronica":
            porcentaje = 21;
            break;
        default:
            porcentaje = 10;
    }
    
    return precio * (porcentaje / 100);
}

console.log(calcularImpuesto("libro", 20)); // Muestra: 0.8 (4% de 20)

Buenas prácticas y limitaciones

Buenas prácticas:

  1. Usar siempre break: A menos que específicamente queramos el comportamiento de fall-through, siempre debemos incluir break al final de cada caso.

  2. Incluir default: Aunque es opcional, es una buena práctica incluir siempre un caso default para manejar valores inesperados.

  3. Preferir constantes sobre variables: Para mejorar la legibilidad, es mejor usar valores constantes en los casos.

  4. Considerar el uso de objetos: Para casos muy complejos o numerosos, a veces un objeto de mapeo puede ser más eficiente.

// Alternativa a switch con un objeto
const diasSemana = {
    1: "Lunes",
    2: "Martes",
    3: "Miércoles",
    4: "Jueves",
    5: "Viernes",
    6: "Sábado",
    7: "Domingo"
};

const dia = diasSemana[3] || "Día no válido";
console.log(dia); // Muestra: "Miércoles"

Limitaciones:

  1. Comparación estricta: switch usa comparación estricta (===), lo que puede ser limitante en algunos casos.

  2. Expresiones limitadas: No es adecuado para comparaciones complejas o de rango.

  3. Solo valores concretos: Solo compara con valores específicos, no permite condiciones como "mayor que" o "menor que".

Ejemplos prácticos

Ejemplo 1: Calculadora simple

function calculadora(a, operacion, b) {
    let resultado;
    
    switch (operacion) {
        case "+":
            resultado = a + b;
            break;
        case "-":
            resultado = a - b;
            break;
        case "*":
            resultado = a * b;
            break;
        case "/":
            if (b === 0) {
                return "No se puede dividir por cero";
            }
            resultado = a / b;
            break;
        default:
            return "Operación no válida";
    }
    
    return resultado;
}

console.log(calculadora(10, "+", 5)); // Muestra: 15
console.log(calculadora(10, "*", 5)); // Muestra: 50
console.log(calculadora(10, "/", 0)); // Muestra: "No se puede dividir por cero"

Ejemplo 2: Convertidor de meses

function obtenerDiasDelMes(mes, anio) {
    let dias;
    
    switch (mes) {
        case 1: // Enero
        case 3: // Marzo
        case 5: // Mayo
        case 7: // Julio
        case 8: // Agosto
        case 10: // Octubre
        case 12: // Diciembre
            dias = 31;
            break;
        case 4: // Abril
        case 6: // Junio
        case 9: // Septiembre
        case 11: // Noviembre
            dias = 30;
            break;
        case 2: // Febrero
            // Comprobación de año bisiesto
            if ((anio % 4 === 0 && anio % 100 !== 0) || anio % 400 === 0) {
                dias = 29;
            } else {
                dias = 28;
            }
            break;
        default:
            return "Mes no válido";
    }
    
    return dias;
}

console.log(obtenerDiasDelMes(2, 2024)); // Muestra: 29 (2024 es bisiesto)
console.log(obtenerDiasDelMes(2, 2023)); // Muestra: 28
console.log(obtenerDiasDelMes(4, 2023)); // Muestra: 30

Ejemplo 3: Evaluación de calificaciones

function obtenerCalificacion(puntuacion) {
    // Aseguramos que puntuacion es un número entre 0 y 100
    puntuacion = Math.max(0, Math.min(100, Math.round(puntuacion)));
    let letra;
    
    switch (Math.floor(puntuacion / 10)) {
        case 10:
        case 9:
            letra = "A";
            break;
        case 8:
            letra = "B";
            break;
        case 7:
            letra = "C";
            break;
        case 6:
            letra = "D";
            break;
        default:
            letra = "F";
    }
    
    return `Puntuación: ${puntuacion}, Calificación: ${letra}`;
}

console.log(obtenerCalificacion(95)); // Muestra: "Puntuación: 95, Calificación: A"
console.log(obtenerCalificacion(81)); // Muestra: "Puntuación: 81, Calificación: B"
console.log(obtenerCalificacion(68)); // Muestra: "Puntuación: 68, Calificación: D"
console.log(obtenerCalificacion(42)); // Muestra: "Puntuación: 42, Calificación: F"

Resumen

La estructura switch es una herramienta poderosa para manejar múltiples condiciones basadas en una misma expresión. Ofrece una alternativa más clara y organizada que múltiples sentencias if/else cuando trabajamos con valores específicos y discretos.

Hemos aprendido la sintaxis básica, la importancia de las sentencias break, el comportamiento de fall-through (ejecución en cascada), y cómo agrupar casos que comparten el mismo código. También hemos explorado los casos de uso más apropiados y algunas buenas prácticas para utilizar esta estructura de manera efectiva.

Aunque tiene algunas limitaciones, como la restricción a comparaciones estrictas y la incapacidad de manejar rangos directamente, el switch sigue siendo una estructura fundamental en JavaScript para ciertos tipos de lógica condicional, especialmente cuando tratamos con valores enumerados o categorías bien definidas.