Skip to content
This page has been auto-translated and may contain errors.View in English

Condicionales

docs.scrimba.com

Un programa que siempre hace lo mismo no es muy útil. Quieres una página que muestre un mensaje a un visitante que ha iniciado sesión y otro a un extraño, un formulario que acepte una edad de 18 pero no de 12, un juego que reporte si ganaste o perdiste. Todo eso necesita una forma de hacer una pregunta y actuar según la respuesta. Eso es lo que hacen los condicionales: permiten que tu código elija qué ejecutar según si algo es verdadero o no.

Ya tienes las piezas. Los operadores de comparación y lógicos producen respuestas verdaderas o falsas, y este capítulo trata sobre actuar basándose en ellas.

Ejecutar código solo cuando una condición es verdadera

Una sentencia if ejecuta un bloque de código solo cuando una condición es verdadera. Escribes la palabra if, una condición entre paréntesis y un bloque entre llaves. Si la condición es verdadera, el bloque se ejecuta. Si no es así, JavaScript omite el bloque y continúa.

js
const age = 20;

if (age >= 18) {
  console.log("Puedes entrar."); // Puedes entrar.
}

La condición age >= 18 es verdadera o falsa. Aquí age es 20, así que es verdadera y el mensaje se imprime. Cambia age a 12 y la condición es falsa, así que el bloque se omite y no se imprime nada.

A menudo quieres una alternativa para cuando la condición es falsa. Para eso está else:

js
const age = 12;

if (age >= 18) {
  console.log("Puedes entrar.");
} else {
  console.log("Vuelve cuando seas mayor."); // Vuelve cuando seas mayor.
}

Exactamente uno de los dos bloques se ejecuta, nunca ambos. Cuando tienes más de dos resultados, else if te permite verificar otra condición:

js
const score = 74;

if (score >= 90) {
  console.log("Calificación: A");
} else if (score >= 70) {
  console.log("Calificación: B"); // Calificación: B
} else {
  console.log("Calificación: C");
}

JavaScript verifica cada condición de arriba hacia abajo y se detiene en la primera que es verdadera. Una puntuación de 74 no es >= 90, pero sí es >= 70, así que imprime Calificación: B y nunca mira el else.

Una sentencia if ejecuta un bloque cuando su condición es verdadera, y un bloque else opcional se ejecuta cuando no lo es. Encadenar con else if te permite verificar varias condiciones en orden.

js
const score = 74;

if (score >= 90) {
  console.log("Calificación: A");
} else if (score >= 70) {
  console.log("Calificación: B"); // Calificación: B
} else if (score >= 50) {
  console.log("Calificación: C");
} else {
  console.log("Calificación: F");
}

El orden es importante y es la parte que la gente se equivoca. JavaScript prueba cada condición de arriba hacia abajo y ejecuta el bloque del primero que es verdadero, luego omite el resto. Por eso los rangos van de alto a bajo aquí: una vez que se alcanza score >= 70, una puntuación de 74 coincide y la cadena se detiene. Si escribieras score >= 50 primero, una puntuación de 74 coincidiría con eso en su lugar y todos los mayores de 50 obtendrían una C.

La condición puede ser cualquier expresión que produzca un valor verdadero o falso, así que puedes combinar verificaciones con los operadores lógicos de operators:

js
const age = 20;
const hasTicket = true;

if (age >= 18 && hasTicket) {
  console.log("Disfruta el espectáculo."); // Disfruta el espectáculo.
} else {
  console.log("Entrada denegada.");
}

Una sentencia if evalúa una condición y ejecuta su bloque cuando el resultado es verdadero, con ramas else if y else opcionales para los otros casos. La cadena está ordenada: JavaScript evalúa las condiciones de arriba hacia abajo y ejecuta el primer bloque cuya condición es verdadera, luego sale de toda la cadena.

js
const score = 74;

if (score >= 90) {
  console.log("Calificación: A");
} else if (score >= 70) {
  console.log("Calificación: B"); // Calificación: B
} else if (score >= 50) {
  console.log("Calificación: C");
} else {
  console.log("Calificación: F");
}

Dos propiedades de esta forma vale la pena retener. Primero, las ramas son mutuamente excluyentes: exactamente una se ejecuta. Por eso los límites aquí solo necesitan un lado cada uno. La rama score >= 70 no necesita score < 90 protegiéndola, porque llegar a esa línea ya significa que la prueba score >= 90 falló. Agregar el límite superior redundante es un instinto común y hace que la cadena sea más difícil de leer, no más segura.

Segundo, la condición se coerciona a un booleano, así que no tiene que ser una comparación literal. Cualquier expresión funciona, y JavaScript aplica sus reglas de truthy y falsy para decidir. Esa flexibilidad es útil y ocasionalmente una trampa, por eso el nivel avanzado de este capítulo vuelve a ella en detalle abajo.

js
const age = 20;
const hasTicket = true;

if (age >= 18 && hasTicket) {
  console.log("Disfruta el espectáculo."); // Disfruta el espectáculo.
} else {
  console.log("Entrada denegada.");
}
JunoEjecutar código solo cuando una condición es verdadera Un if ejecuta su bloque solo cuando la condición entre paréntesis es verdadera, y else te da una alternativa para cuando no lo es. Agrega else if cuando hay más de dos resultados. JavaScript verifica de arriba hacia abajo y se detiene en la primera coincidencia, así que ordena tus condiciones de una manera que tenga sentido.
JunoEjecutar código solo cuando una condición es verdadera Una cadena if / else if / else ejecuta el bloque de la primera condición verdadera y omite el resto, así que el orden no es decoración, es lógica. Los rangos van de alto a bajo por exactamente esa razón. La condición puede ser cualquier expresión que se resuelva en verdadero o falso, así que combina verificaciones con los operadores lógicos cuando necesites hacerlo.
JunoEjecutar código solo cuando una condición es verdadera La cadena es mutuamente excluyente y se evalúa de arriba hacia abajo, así que cada rama solo necesita el límite que las ramas arriba ya no han descartado. Agregar el límite superior redundante se lee como precaución pero es realmente solo ruido. Y la condición se coerciona a un booleano, lo que es una característica hasta que un valor inesperado se cuela, así que ten en mente las reglas de truthy y falsy.

Elegir un valor con el operador ternario

A veces un if / else hace un trabajo pequeño: elegir entre dos valores. Para eso existe una forma más corta llamada operador ternario. Escribes una condición, un ?, el valor a usar cuando es verdadera, un : y el valor a usar cuando es falsa.

js
const age = 20;
const message = age >= 18 ? "Bienvenido" : "Muy joven";

console.log(message); // Bienvenido

Léelo como una pregunta: ¿es age >= 18? Si sí, message se convierte en "Bienvenido"; si no, se convierte en "Muy joven". Esa es la misma decisión que un if / else haría, en una línea.

El ternario es mejor cuando estás eligiendo un valor para guardar o imprimir. Cuando una rama necesita hacer varias cosas, una sentencia if es más clara, así que usa el ternario solo cuando cada lado es un valor único.

El operador ternario elige entre dos valores basándose en una condición: condition ? valueIfTrue : valueIfFalse. A diferencia de una sentencia if, es una expresión, así que produce un valor que puedes asignar o colocar directamente en un template literal.

js
const score = 82;
const passed = score >= 60 ? "aprobado" : "reprobado";

console.log(`Resultado: ${passed}`); // Resultado: aprobado

Aquí es donde se gana su lugar. Asignar uno de dos valores a una variable es un trabajo que el ternario hace en una línea, mientras que la versión if extiende la misma lógica en cinco líneas y repite la asignación en ambas ramas:

js
// La versión if hace lo mismo con más ceremonia:
let passed;
if (score >= 60) {
  passed = "aprobado";
} else {
  passed = "reprobado";
}

Donde deja de ayudar es cuando las ramas hacen más que producir un valor. Si cualquiera de los lados necesita ejecutar varias sentencias, o encuentras que estás anidando un ternario dentro de otro, la legibilidad que ganaste se ha ido. En ese punto una sentencia if es la opción más clara.

El operador ternario es el único operador en JavaScript que toma tres operandos: condition ? valueIfTrue : valueIfFalse. La distinción que lo hace útil es que es una expresión, no una sentencia. Se evalúa a un valor, así que encaja en lugares donde una sentencia no puede ir: el lado derecho de una asignación, un argumento, un template literal.

js
const score = 82;
const label = score >= 60 ? "aprobado" : "reprobado";

console.log(`Resultado: ${label}`); // Resultado: aprobado

Úsalo cuando todo el trabajo es seleccionar entre dos valores, y preférelo sobre un if allí porque mantiene la asignación en un solo lugar en lugar de repetirla en ambas ramas. Usa un ternario para elegir un valor, no para ejecutar una rama.

El modo de fallo es la anidación. Un ternario cuyas ramas son a sí mismas ternarios técnicamente funciona, pero obliga al lector a analizar de derecha a izquierda y mantener varias condiciones en su cabeza a la vez:

js
// Difícil de leer. Prefiere una cadena if o un switch aquí.
const grade = score >= 90 ? "A" : score >= 70 ? "B" : score >= 50 ? "C" : "F";

Esa línea produce la respuesta correcta y cuesta un esfuerzo real al siguiente lector. Cuando una decisión tiene más de dos resultados, una cadena if o un switch la expresa mucho más claramente, que es la siguiente sección.

JunoElegir un valor con el operador ternario El ternario es una forma compacta de elegir entre dos valores: condition ? valueIfTrue : valueIfFalse. Brilla cuando estás eligiendo algo para guardar o imprimir. Si una rama necesita hacer más que devolver un valor único, usa un if completo en su lugar, será más legible.
JunoElegir un valor con el operador ternario Un ternario es una expresión, así que devuelve un valor que puedes asignar o colocar en un template literal, lo que una sentencia if no puede hacer. Eso lo hace la opción clara para elegir uno de dos valores, ya que la versión if repite la asignación en ambas ramas. Una vez que las ramas hacen trabajo real, o empiezas a anidar ternarios, vuelve a un if.
JunoElegir un valor con el operador ternario El ternario es una expresión, así que va donde una sentencia no puede: una asignación, un argumento, un template literal. Úsalo para elegir un valor, no para ejecutar una rama, y se mantiene legible. Anida uno dentro de otro y deja de valer la pena, así que una decisión de múltiples resultados pertenece a una cadena if o un switch.

Comparar un valor contra casos fijos con switch

Cuando estás verificando un valor contra una lista de posibilidades fijas, una sentencia switch puede ser más ordenada que una larga cadena if / else if. Le das el valor a verificar, luego listas los casos contra los que compararlo.

js
const day = "Mar";

switch (day) {
  case "Sab":
    console.log("Fin de semana");
    break;
  case "Dom":
    console.log("Fin de semana");
    break;
  default:
    console.log("Día de semana"); // Día de semana
}

El switch compara day con cada case a su vez. Cuando encuentra una coincidencia, ejecuta el código de ese case. break le dice que se detenga; sin él, JavaScript sigue ejecutando en el siguiente case. default es la alternativa que se ejecuta cuando ningún case coincide, como el else final en una cadena.

Olvidar break es el error clásico de switch. Omítelo y tu código ejecutará el case coincidente y luego cada case debajo de él hasta que golpee un break o el final, lo cual casi nunca es lo que quisiste.

Una sentencia switch compara un valor contra un conjunto de casos fijos. Se lee más claramente que una larga cadena if / else if cuando cada rama está probando el mismo valor para igualdad.

js
const status = "enviado";

switch (status) {
  case "pendiente":
    console.log("Pedido recibido.");
    break;
  case "enviado":
    console.log("En camino."); // En camino.
    break;
  case "entregado":
    console.log("Entregado.");
    break;
  default:
    console.log("Estado desconocido.");
}

Tres cosas llevan la lógica. case marca un valor a comparar, break finaliza el case coincidente, y default maneja cualquier cosa que no coincida. La comparación usa igualdad estricta (===), así que case "1" no coincidirá con un número 1.

La trampa es el fall-through. Un case sin un break no se detiene; la ejecución continúa en los siguientes cases hasta que golpea un break o el final del switch. Eso es usualmente un bug, pero también es ocasionalmente útil cuando varios cases comparten un resultado:

js
const day = "Sab";

switch (day) {
  case "Sab":
  case "Dom":
    console.log("Fin de semana"); // Fin de semana
    break;
  default:
    console.log("Día de semana");
}

Aquí "Sab" coincide y cae a través del bloque compartido para "Dom", así que ambos días de fin de semana ejecutan la misma línea. Ese es fall-through usado a propósito, y solo se lee claramente porque los cases vacíos se apilan directamente encima del bloque compartido.

Una sentencia switch toma un valor único y lo compara contra una serie de etiquetas case, ejecutando el bloque de la primera que coincide. La comparación es igualdad estricta (===), lo que importa: case "1" no coincide con el número 1, y no hay coerción de tipo que te salve.

js
const status = "enviado";

switch (status) {
  case "pendiente":
    console.log("Pedido recibido.");
    break;
  case "enviado":
    console.log("En camino."); // En camino.
    break;
  case "entregado":
    console.log("Entregado.");
    break;
  default:
    console.log("Estado desconocido.");
}

El mecanismo que la gente subestima es el fall-through. Un switch no ejecuta un case y se detiene; salta a la etiqueta coincidente y luego ejecuta directamente hasta que golpea un break o la llave de cierre, ignorando los límites de los cases en el camino. Un break faltante ejecuta cada case debajo de la coincidencia. Esa es la fuente de la mayoría de los bugs de switch, y también es el único uso deliberado del comportamiento, apilando etiquetas para que varios valores compartan un bloque:

js
const day = "Sab";

switch (day) {
  case "Sab":
  case "Dom":
    console.log("Fin de semana"); // Fin de semana
    break;
  default:
    console.log("Día de semana");
}

default no tiene que venir al final, aunque poner al final es la convención que mantiene los switches legibles. También nota que un switch solo prueba un valor para igualdad, así que una cadena de verificaciones de rango como el ejemplo de calificación anterior no puede convertirse en un switch. Ese límite es exactamente lo que te dice cuándo un switch es la herramienta correcta, que la última parte de este nivel analiza.

JunoComparar un valor contra casos fijos con switch Un switch verifica un valor contra una lista de opciones case y ejecuta la que coincide, con default como la alternativa general. Siempre termina cada case con break, o JavaScript sigue ejecutando en los cases debajo. Ese break faltante es el error que casi todos cometen al menos una vez.
JunoComparar un valor contra casos fijos con switch Usa un switch cuando cada rama está probando el mismo valor para igualdad contra casos fijos, y recuerda que coincide con ===, así que "1" no es 1. Cada case necesita un break o cae a través en el siguiente. Ese fall-through es un bug por defecto, pero apilar cases vacíos encima de un bloque compartido es la única vez que lo quieres.
JunoComparar un valor contra casos fijos con switch Un switch coincide con un valor con igualdad estricta y luego ejecuta hacia abajo hasta un break, ignorando los límites de los cases, así que un break faltante ejecuta cada case debajo de la coincidencia. Apilar etiquetas encima de un bloque compartido es el único uso deliberado de eso. Porque solo prueba igualdad en un valor único, un conjunto de verificaciones de rango permanece en una cadena if.

Elegir la herramienta correcta

Ahora tienes tres formas de tomar una decisión, y la elección es principalmente sobre ajuste. Usa una cadena if / else if / else para la mayoría de ramificaciones, especialmente cuando las condiciones son rangos o combinaciones. Usa un ternario cuando estés eligiendo uno de dos valores para guardar o imprimir. Usa un switch cuando estés verificando un valor contra un puñado de opciones fijas.

Ninguno de estos es más avanzado que los otros. Usa el que expresa tu decisión más claramente, y si no estás seguro, una sentencia if es siempre una opción segura.

Las tres formas se superponen, así que la habilidad útil es emparejar la herramienta con la forma de la decisión. Una cadena if maneja cualquier cosa, y es la llamada correcta siempre que las condiciones sean rangos (score >= 70) o combinaciones (age >= 18 && hasTicket). Un ternario es para elegir entre dos valores en una expresión. Un switch encaja cuando un valor único se prueba para igualdad contra varios casos fijos, como un estado o un nombre de día.

Una regla previene mucho código enredado: usa la forma que se lee más claramente, no la más corta. Un ternario anidado es más corto que una cadena if y peor de leer, así que la longitud no es el objetivo. La claridad para la siguiente persona, que a menudo eres tú en un mes, es.

Tres herramientas, y los límites entre ellas se reducen a la forma de la decisión. Una cadena if es la forma general: maneja rangos, combinaciones y cualquier cosa que una condición pueda expresar, así que es la predeterminada siempre que las ramas no sean todas pruebas de igualdad en un valor. Un ternario se estrecha a un trabajo único, elegir uno de dos valores como una expresión, y paga solo mientras ambas ramas se mantengan simples. Un switch encaja cuando un valor se compara para igualdad contra un conjunto fijo de casos.

Hay una cuarta opción que vale la pena nombrar aunque esté fuera del alcance aquí: cuando estés mapeando un valor a un resultado, un objeto de búsqueda a menudo vence a los tres. Un switch que solo asigna un valor por case, o una larga cadena if de pruebas value === "x", es frecuentemente más clara como un objeto plano que indexas. Encontrarás ese patrón una vez que objects esté en la mesa; por ahora, nota cuándo un switch es realmente una tabla disfrazada.

Dos más hábitos avanzados redondean esto. El primero es los valores truthy y falsy, porque una condición no necesita ser una comparación. JavaScript coerciona la condición a un booleano, y los valores que resultan falsos son un conjunto fijo y corto: false, 0, "" (la cadena vacía), null, undefined, y NaN. Todo lo demás es truthy. Por eso if (name) es una abreviatura común para "name no está vacío", y también por qué puede sorprenderte: un valor de 0 es un número real pero una condición falsy, así que if (count) omite el bloque cuando count es 0. Conoce el conjunto falsy y estas verificaciones dejan de ser adivinanzas.

El segundo es la cláusula de guardia. Cuando una decisión es realmente sobre salir temprano, un if profundamente anidado se lee peor que verificar la condición de salida primero y detenerse. Esa forma de "verificar el caso malo, detener, luego continuar con el buen camino" es la cláusula de guardia, y mantiene la lógica principal sin indentar en lugar de enterrada dentro de ramas. La parte de detención usualmente significa devolver salida de una función, que es el próximo capítulo, functions, así que el patrón completo llega allí. La idea a llevar ahora es que aplanar una decisión manejando el caso excepcional primero es casi siempre más clara que anidar el caso normal más profundo y más profundo.

JunoElegir la herramienta correcta Usa una cadena if para la mayoría de decisiones, un ternario cuando estés eligiendo uno de dos valores, y un switch cuando estés emparejando un valor contra opciones fijas. Ninguno de ellos es más sofisticado que los otros. Elige cualquiera que exprese tu decisión más claramente, y usa por defecto if cuando no estés seguro.
JunoElegir la herramienta correcta Empareja la herramienta con la forma: if para rangos y combinaciones, un ternario para elegir uno de dos valores, un switch para igualdad contra casos fijos. Usa la forma que se lee más claramente, no la más corta, porque un ternario anidado es corto y difícil de seguir. El siguiente lector a menudo eres tú, así que escribe para ellos.
JunoElegir la herramienta correcta La cadena if es la herramienta general, el ternario es para elegir uno de dos valores, y el switch es para igualdad contra un conjunto fijo, con un objeto de búsqueda a menudo venciendo a un switch de mapeo de valores una vez que tienes objetos. Mantén el conjunto falsy en tu cabeza (false, 0, "", null, undefined, NaN) así que un if (count) desnudo no te sorprende cuando el conteo es cero. Y cuando una decisión es realmente una salida temprana, maneja el caso malo primero y aplana el anidamiento; la cláusula de guardia completa llega con funciones.

A dónde van los condicionales desde aquí

Los condicionales son cómo un programa deja de ser un script fijo y comienza a responder a su entrada. Los usarás constantemente, y se combinan con todo alrededor: las respuestas verdadero-o-falso vienen de operators, y las decisiones que tomas aquí comienzan a valer la pena una vez que puedas ejecutarlas repetidamente sobre datos con loops y empaquetarlas en functions.

El próximo capítulo, loops, agrega la otra mitad del flujo de control: no solo elegir si ejecutar código, sino ejecutarlo una y otra vez hasta que una condición te dice que te detengas.