Original article: Fall-Through in JavaScript Switch Statements – Explained with Examples

Las sentencias switch en JavaScript tienen un comportamiento de falla (fall-through) que puede provocar resultados inesperados. Explicare qué es este comportamiento, como evitarlo y casos de uso.

Las sentencias switch le permiten crear declaraciones condicionales en JavaScript. Estas tienen una expresión condicional y, dependiendo del valor retornado de esa expresión, puedes tener diferentes casos; se ejecutará el caso que coincida con esa expresión.

Veamos el comportamiento de falla en caída de las sentencias switch.

¿Qué es el comportamiento de falla en caída?

Veamos este ejemplo con switch:

const expresion = 10 - 5

switch (expresion) {
  case 1:
    console.log("El resultado es 1")
    break

  case 5:
    console.log("El resultado es 5")
    break

  case 10:
    console.log("El resultado es 10")
    break

  default:
    console.log("El resultado no existe")
}

// El resultado es 5

Aquí tenemos la expresión 10 - 5. Usando el operador switch, evaluamos diferentes casos, uno de los cuales coincide con el valor regresado por la expresión.

En el ejemplo, el case 5 coincide con la expresión, por lo que se ejecutará el código console.log("El resultado es 5").

Como puede ver el resultado es "El resultado es 5".

Si la expresión fuera 10 - 1, el resultado será 9. Como no hay ningún caso para este valor, se ejecutará el caso por defecto y el resultado será:

// El resultado no existe

Una sentencia común que se encuentra en todos los casos es la sentencia break. ¿Y si esta sentencia no estuviera declarada? Veamos qué pasaría:

const expresion = 10 - 5

switch (expresion) {
  case 1:
    console.log("El resultado es 1")

  case 5:
    console.log("El resultado es 5")

  case 10:
    console.log("El resultado es 10")

  default:
    console.log("El resultado no existe")
}

// El resultado es 5
// El resultado es 10
// El resultado no existe

¿Qué notaste?

Se ejecutaron el case 5, case 10 y el caso por defecto. Este es el comportamiento de falla en caída.

Cuando tiene varios case, la sentencia switch encuentra el primer caso que coincida con la expresión. Comienza desde el case 1. Ese caso no coincide, por lo que el switch continúa la búsqueda. Luego encuentra el case 5. Este caso coincide con la expresión.

Cuando el switch encuentra este primer caso que coincide con la expresión, realiza un análisis alternativo donde ejecuta los casos restantes después del caso coincidente. No importa si estos casos coinciden o no con la expresión, siempre serán ejecutados.

Probablemente estés pensando, ¿Cuál es el beneficio de este comportamiento? Lo veremos más adelante en este artículo.

La palabra reservada break en sentencias switch

La palabra reservada break como vio en el primer ejemplo, es una manera de verificar que la sentencia switch no falle. Sin esta declaración, se produce una falla, esto significa que se ejecutara el caso que coincida con la expresión además de todos los demás casos siguientes.

Tenemos un break en el caso 10:

const expresion = 10 - 5

switch (expresion) {
  case 1:
    console.log("El resultado es 1")

  case 5:
    console.log("El resultado es 5")

  case 10:
    console.log("El resultado es 10")
    break

  default:
    console.log("El resultado no existe")
}

// El resultado es 5
// El resultado es 10

Del anterior ejemplo, ¿Qué notas aquí? Se ejecuta el caso 5 coincidente. Mostramos por consola "El resultado es 5". No hay una sentencia break, por lo tanto, la sentencia switch continua con los casos siguientes.

Se ejecuta el case 10, que es el siguiente caso después del case 5. Tenemos "El resultado es 10". Luego la sentencia switch encuentra un break y los casos restantes no se ejecutan.

Ahora notas por que debemos tener un break en todos los casos:

const expresion = 10 - 5

switch (expresion) {
  case 1:
    console.log("El resultado es 1")
	break
  case 5:
    console.log("El resultado es 5")
	break
  case 10:
    console.log("El resultado es 10")
    break

  default:
    console.log("El resultado no existe")
}

// El resultado es 5

Esto es importante para poder ejecutar solo el caso que coincida con nuestra expresión.

¿El caso por defecto necesita una sentencia break?

En nuestro ejemplo cada caso tiene una sentencia break menos el caso por defecto. Entonces, ¿el caso por defecto necesita un break? Bueno, depende de la ubicación del caso por defecto.

En nuestro ejemplo, el caso por defecto es el último. Cuando se ejecuta este caso (no hay ningún caso coincidente con la expresión), se espera que haya un error porque no hay una sentencia break.

Pero dado que el caso por defecto es el último, no hay ningún caso posterior en el que la sentencia switch no se cumpla.

Ahora, supongamos que tenemos un orden diferente para el caso por defecto:

const expresion = 10 - 1

switch (expresion) {
  case 1:
    console.log("El resultado es 1")

  default:
    console.log("El resultado no existe")

  case 5:
    console.log("El resultado es 5")

  case 10:
    console.log("El resultado es 10")
}

// El resultado no existe
// El resultado es 5
// El resultado es 10

Aquí, la expresión es 10 - 1, y hemos eliminado todos los break. El caso por defecto es el segundo de la sentencia switch. ¿Qué notas en los resultados?

Como no hay ningún caso que coincida con la expresión, se ejecuta el caso por defecto. Pero este caso no tiene un break y hay otros casos debajo del mismo. Entonces los casos (5 y 10) posteriores al caso por defecto también se ejecutarán.

Por eso depende de la ubicación en que se coloque el caso por defecto. En este ejemplo sería importante agregar una sentencia break al valor por defecto. De esta manera podemos omitir la sentencia break del caso 10 ya que es el último caso.

const expresion = 10 - 1

switch (expresion) {
  case 1:
    console.log("El resultado es 1")
    break

  default:
    console.log("El resultado no existe")
    break

  case 5:
    console.log("El resultado es 5")
    break

  case 10:
    console.log("El resultado es 10")
}

// El resultado no existe

Beneficios del comportamiento de falla en caída

Este comportamiento puede parecer un error, pero en realidad no lo es. Tiene un beneficio. Puede usar este comportamiento para agrupar casos relacionados. Por ejemplo:

const expresion = 10 - 2

switch (expresion) {
  case 2:
    console.log("El resultado es menor que 8")
    break;

  case 5:
    console.log("El resultado es menor que 8")
    break;

  case 8:
    console.log("El resultado es 8")
    break;

  default:
    console.log("El resultado no existe")
}

// El resultado es 8

Aquí tenemos una condición de 10 - 2. El caso 8 coincide con esta expresión, por lo que tenemos "El resultado es 8" por consola.

Si cambiamos la condición a 10 - 8, el caso 2 coincidirá con la expresión y tendremos "El resultado es menor que 8" por consola.

Si cambiamos la condición a 10 - 5, el caso 5 coincidirá con la expresión y tendremos "El resultado es menor que 8" por consola.

¿Nota que el código para este caso es similar al del caso 2? Entonces, en lugar de escribirlos por separado, podemos agruparlos.

Así:

const expresion = 10 - 5

switch (expresion) {
  case 2:

  case 5:
    console.log("El resultado es menor que 8")
    break;

  case 8:
    console.log("El resultado es 8")
    break;

  default:
    console.log("El resultado no existe")
}

// El resultado es menor que 8

Al eliminar el código y la palabra reservada break del caso 2, podemos combinar el caso 2 con el caso 5. Con una condición de 10 - 5, el caso 5 coincide y tenemos "El resultado es menor que 8" por consola.

Con la condición de 10 - 8, el caso 2 coincidirá. No hay código en el caso 2, por lo que no se ejecutará nada. Además, no hay un break, por lo que se produce una falla, eso significa que se ejecutará el siguiente caso, el caso 5.

Después de la ejecución tenemos "El resultado es menor que 8" impreso en la consola. La sentencia switch encuentra un break por lo que sabe que debe detenerse.

Pudimos agrupar el caso 2 y el caso 5, ya que están relacionados, aprovechando el comportamiento de fallo en caída. Hay muchos escenarios donde puedes utilizar este comportamiento.

Para finalizar

En este artículo, analizamos el comportamiento fallo en caída de las sentencias switch. Este comportamiento implica ejecutar otros casos después del caso coincidente de una expresión. Ocurre de manera predeterminada, pero se puede evitar con la palabra reservada break como vimos en diferentes ejemplos.

También vimos el beneficio de este comportamiento, ya que ayuda agrupar casos relacionados.

Cuando empecé a aprender JavaScript, aprendí a usar siempre break en mis sentencias switch pero nunca entendí completamente por qué. Pensé que solo era la sintaxis de las sentencias switch.

Pero solo después de un tiempo logre comprender lo que hacía break, evitar fallos.

Quizá tengas una historia similar, o quizás no, pero espero que este articulo te enseñe algo sobre las sentencias switch. Por favor compártelo si te resulto útil.