En programación los condicionales son pequeñas decisiones que determinan cómo funcionan grandes cosas.
  En el capítulo anterior, Comparaciones y operadores lógicos, analizamos los comparadores (=== y !==) y los operadores booleanos (&&, || y !). 
  Dichos comparadores y operadores, junto con los valores booleanos presentados en el capítulo Tipos de datos básicos: boolean, number y string, son la base sobre la que se asienta la instrucción condicional if-else que se presenta en este capítulo.
  Este capítulo también aborda el uso de la instrucción switch cuyo uso, como veremos, evita largas cadenas de instrucciones if-else.
  Finalmente el capítulo expone el operador ternario de JS (expresion ? instrucción : instrucción) que permite devolver un valor a partir de la evaluación de una expresión.
Índice
if-else
  La instrucción if-else nos permite ejecutar una instrucción o un bloque de código en base a la evaluación de expresiones como valores booleanos:
const booleanOperator1 = true
const booleanOperator2 = false
if (booleanOperator1 || booleanOperator2) {
  // Este bloque de código se ejecuta
  // porque la expresión
  // (booleanOperator1 || booleanOperator2)
  // se evalúa como true
  console.log("booleanOperator1 o booleanOperator2 es true")
}
if (booleanOperator1)
  // La siguiente instrucción se ejecuta
  // porque la expresión (booleanOperator1)
  // se evalúa como true
  console.log("booleanOperator1 es true")
if (booleanOperator1)
  // La siguiente instrucción se ejecuta
  // porque la expresión (booleanOperator1)
  // se evalúa como true
  console.log("booleanOperator1 es true")
else {
  // Este bloque no se ejecuta
  // porque la expresión (booleanOperator1)
  // no se evalúa como false
  console.log("booleanOperator1 no es true")
}
  Como se aprecia en el ejemplo anterior, el uso de else es opcional. También lo es el uso de bloques de código (una o más instrucciones entre los símbolos { y }) cuando el bloque de código está compuesto por una única instrucción.
  JS permite el uso de if anidados, así como el uso de cadenas de else:
const boolOperator1 = true
const boolOperator2 = false
// if anidados
// Imprime "boolOperator es true"
if (boolOperator1 || boolOperator2) {
  if (boolOperator1) {
    if (boolOperator2)
      console.log("boolOperator1 y boolOperator2 son true")
    else
      console.log("boolOperator1 es true")
  } else
    console.log("boolOperator2 es true")
} else
  console.log("boolOperator1 y boolOperator2 son false")
// Cadena de else
// Imprime "boolOperator es true"
if (boolOperator1 && boolOperator2)
  console.log("boolOperator1 y boolOperator2 son true")
else if (boolOperator1)
  console.log("boolOperator1 es true")
else if (booleanOperator2)
  console.log("boolOperator2 es true")
else
  console.log("boolOperator1 y boolOperator2 son false")
  Al anidar instrucciones if-else hay que ser cuidadoso con la definición de los bloques de código, ya que su uso incorrecto puede llevarnos a confusiones, como se muestra en el siguiente ejemplo:
const boolOperator1 = false;
const boolOperator2 = true;
// Aunque la indentación del código hace pensar
// que se imprimirá "boolOperator1 es false",
// realmente NO se imprime nada
if (boolOperator1)
  if (boolOperator2)
    console.log("boolOperator1 y boolOperator2 son true")
else
  console.log("boolOperator1 es false")
// El código anterior PARECE ser equivalante a este
if (boolOperator1) {
  if (boolOperator2) {
    console.log("boolOperator1 y boolOperator2 son true")
  }
} else {
  console.log("boolOperator1 es false")
}
// Pero en realidad ES equivalente a este
if (boolOperator1) {
  if (boolOperator2) {
    console.log("boolOperator1 y boolOperator2 son true")
  } else {
    console.log("boolOperator1 es false")
  }
}
  Como regla general, para no meterte en este tipo de charcos define claramente los bloques de código cuando anides instrucciones if-else.
Conversión implícita
  Decía al principio de esta sección que if-else nos permite ejecutar una instrucción o un bloque de código en base a la evaluación de expresiones como valores booleanos.
  Esto tan sofisticado simplemente viene a significar que if-else va a evaluar una expresión en un contexto booleano para decidir si ejecuta el bloque de código asociado al if o al else. 
  Puesto que evalúa una expresión como booleana, la instrucción if-else es capaz de convertir implícitamente el resultado de la expresión entre paréntesis en un valor booleano siguiendo las reglas de conversión expuestas en el capítulo Tipos de datos básicos: boolean, number y string. Veámoslo con algunos ejemplos:
const nonEmptyString = "Una cadena no vacía"
const zero = 0
// En un contexto booleano (nonEmptyString)
// se evalúa como true:
// Boolean(nonEmptyString) es true
if (nonEmptyString)
  console.log("nonEmptyString es una cadena no vacía")
else
  console.log("nonEmptyString es una cadena vacía")
  
// En un contexto booleano (zero)
// se evalúa como false:
// Boolean(zero) es false
if (zero)
  console.log("zero no es 0")
else
  console.log("zero es 0")
switch
  Hemos visto en la sección anterior que se pueden construir cadenas de else con el comando if-else. Aunque posible, las cadenas de else pueden acabar siendo realmente difíciles de leer y escribir:
const myNumber = 6
// Imprime "myNumber es mayor de 4"
if (myNumber < 0)
  console.log("myNumber es menor de cero")
else if (myNumber === 1)
  console.log("myNumber es 1")
else if (myNumber === 2)
  console.log("myNumber es 2")
else if (myNumber === 3)
  console.log("myNumber es 3")
else if (myNumber === 4)
  console.log("myNumber es 4")
else
  console.log("myNumber es mayor de 4")
La instrucción switch nos permite prescindir de largas cadenas de else en favor de un comando mucho más compacto que evalua una expresión y los compara con distintos valores:
const myNumber = 6
// Imprime "myNumber es mayor de 4"
switch(myNumber) {
  case 1:
    console.log("myNumber es 1")
    break
  case 2:
    console.log("myNumber es 2")
    break
  case 3:
    console.log("myNumber es 3")
    break
  case 4:
    console.log("myNumber es 4")
    break
  default:
    if (myNumber < 0)
      console.log("myNumber es menor de 4")
    else
      console.log("myNumber es mayor de 4")
}
  El ejemplo anterior permite ver que la sección case no trabaja con bloques de código (comandos entre los símbolos { y }), sino con una secuencia de instrucciones que debe finalizar con break.
  Sin break, el runtime que ejecutase el código (en el contexto de este curso node) continuaría ejecutando instrucciones de las siguientes secciones case hasta finalizarlas o encontrar un break.
const myNumber = 1
// Puesto que el primer case no tiene break
// imprimirá "myNumber es 1" y "myNumber es 2"
switch(myNumber) {
  case 1:
    console.log("myNumber es 1")
  case 2:
    console.log("myNumber es 2")
    break
}
  Para finalizar, ten en cuenta que el comando switch NO realiza conversiones implícitas, tal como se muestra en el siguiente ejemplo:
// emptyString convierte a false
const emptyString = ""
switch(emptyString) {
  case false:
    // ESTO NUNCA SE EJECUTARÁ
    // Si switch() realizase conversiones implícitas
    // convertiría emptyString a boolean (false)
    // para compararlo con el valor false, lo que
    // haría que se ejecutase la siguiente instrucción
    console.log("(emptyString) === false")
    break
  
  case "":
    // Puesto que switch() no realiza conversiones
    // implícitas y emptyString === "", se ejecutan 
    // la siguientes instrucción
    console.log("(emptyString) === ''")
}
  Si te has fijado, no he usado break en el último case el ejemplo anterior: Puesto que no hay más case tras el último ¿por qué usar un break?.
 Bien, pues esto NO es una buena idea: Si una modificación posterior al código expuesto añadiese un case adicional, habrian muchísimas posibilidades de que el programador no detectase la falta del break en el último case existente, con lo que se ejecutarían el penúltimo y último. Como regla general agrega siempre un break al final de cada case.
El operador ternario
  El operador ternario es una combinación de evaluación de condición y asignación en una sola expresión, un híbrido de if-else y =. Veámoslo en acción con un ejemplo:
const truthy = true
let myVariable
// Asignación en base a la evaluación
// de una instrucción if-else
if (truthy)
  myVariable = "truthy es true"
else
  myVariable = "truthy es false"
// Misma operación realizada con un ternario
// ... en una sola línea
myVariable = truthy ? "truthy es true" : "truthy es false"
// ... o indentado para mejor legibilidad
myVariable = truthy 
  ? "truthy es true"
  : "truthy es false"
}
  El nombre de ternario viene del hecho de tener tres partes: Una primera parte que se evalua como expresión boolean, una segunda parte que se devuelve si la expresión booleana es verdadera, y una tercera parte que se devuelve si la expresión booleana es falsa. Explico esto para incidir en el hecho de el ternario siempre va a tener tres partes, siempre va a ser un if-else.
  Como la instrucción if-else, los ternarios se pueden anidar:
const truthy = true
const falsy = false
let myVariable
myVariable = falsy
  ? "falsy es true"
  : truthy
    ? "truthy es true"
    : "truthy es false"
}
Ten en cuenta que los ejemplos anteriores muestra el ternario dividido en varias líneas de código. Esta división se hace solamente para crear ejemplos más legibles, pero el ternario, anidado o no, puede escribirse en una sola línea (aunque esto dificulte su legibilidad).
Objetivos conseguidos
  En este capítulo, el último del bloque dirigido a presentar la sintáxis básica de JS, has aprendido a utilizar la indispensable instrucción if-else, así como su equivalente en forma de ternario.
  También has aprendido a utilizar la instrucción switch(), que permite prescindir de largas cadenas de else en favor de una instrucción mucho más visible. No menos importante, hemos aprendido también cuáles son sus limitaciones: solamente permite comprar resultados de expresiones con valores y no realiza conversiones implícitas.
Próximos pasos
¡Enhorabuena! Has completado el bloque de sintáxis básica y ya estás preparado para abordar el tecer bloque de este curso, que introduce las estructuras de iteración, las funciones, los arrays y los objetos.
Pero antes de lanzarte a ello, vamos a consolidar los conceptos aprendidos con una serie de ejercicios que cubren todo lo expuesto en este bloque. Además, como previa a la ejecución de dichos ejercicios, vamos a aprender cómo depurar programas en VSCode, y de eso va el próximo capítulo del bloque: Depuración en Visual Studio Code.
