Aprende leyendo en orden

Booleanos y comparación — la diferencia entre == y ===

Aprende a comparar en JavaScript: la diferencia entre === y ==, cómo construir condiciones y los 6 valores falsy.

¿Se cumple el mínimo para el envío gratis? ¿El usuario ha iniciado sesión? ¿Queda algo en stock? Cambiar lo que se ve en pantalla siempre empieza por comprobar si se cumple una condición.

Este artículo trata la diferencia entre === y == para comprobar la igualdad, los operadores de comparación y lógicos con los que se construyen condiciones, y los 6 valores falsy (valores que actúan como falso dentro de una condición) que JavaScript da por "no se cumple".

Comprobar igualdad — la diferencia entre === y ==

Imagina que comparas un valor escrito en un campo de entrada con otro que el sistema ya tiene guardado. Aunque parezcan iguales, porque los dos son 0, el del campo de entrada es la cadena "0" y el guardado es el número 0.

Para decidir si esos dos se consideran "iguales", JavaScript ofrece dos operadores distintos.

=== devuelve true solo cuando coinciden tanto el tipo como el valor. Si los tipos no coinciden, devuelve false de inmediato.

El otro, ==, convierte primero uno de los lados para igualar los tipos y después compara los valores. "0" y 0 dan false con === y true con ==. Para comprobar la desigualdad también hay dos operadores: !== y !=.

=== y == siguen pasos distintos
"0" === 0Tipos distintos:ahí se detienefalse"0" == 0Convierte, luegocompara valorestrue0 === 0Mismo tipo,mismo valortrue
=== devuelve false de inmediato si los tipos no coinciden; == primero iguala los tipos y después compara.

La conversión, aquí, consiste en leer el carácter "0" como el número 0. El problema es que == aplica esa conversión sin avisar, antes de comparar.

Como compara los resultados ya convertidos, la comprobación no siempre responde a lo que escribiste: valores de aspecto muy distinto, como la cadena vacía "" y 0, pueden acabar dando true.

Cada combinación de tipos tiene fijada su regla de conversión, pero, en vez de memorizarla, resulta más fácil seguir los resultados si usas === y evitas la conversión por completo. En código nuevo, usa === y !==, e iguala los tipos antes de comparar. En el siguiente artículo, sobre conversión de tipos, veremos hacia dónde convierte cada caso y cómo igualar los tipos tú mismo.

== aplica una conversión antes de comparar
"" == 0Se aplica laconversióntrue"0" == 0Se aplica laconversióntrue"" === 0Sin conversiónfalse
== compara los resultados ya convertidos, de modo que el resultado no siempre responde a lo que escribiste. Con === no hay conversión. En el siguiente artículo veremos hacia dónde convierte cada caso.
const typedQuantity = "3";   // cantidad escrita en un campo de entrada (string)
const savedQuantity = 3;     // cantidad guardada (number)

console.log(typedQuantity === savedQuantity);  // false  los tipos difieren
console.log(typedQuantity == savedQuantity);   // true   iguala los tipos y después compara

// Con el mismo tipo, === compara sin problema
console.log(savedQuantity === 3);   // true
console.log(savedQuantity !== 3);   // false  la negación de ===

console.log("" == 0);         // true   la cadena vacía también se convierte en 0
console.log("100" === 100);   // false  === nunca convierte

Compara unas existencias escritas en un campo de entrada con las existencias que guarda el sistema. La cadena typedStock y el número storedStock ya están declarados.

① Muestra el resultado de comparar los dos con ==.

② Muestra el resultado de comparar esos mismos dos con ===.

③ Comprueba y muestra si esos dos son distintos teniendo en cuenta también el tipo.

(Si se ejecuta correctamente, aparecerá una explicación.)

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Construir condiciones — operadores de comparación y lógicos

En una comprobación real no basta con saber si dos valores son iguales. Necesitarás condiciones del tipo "¿el total llega a 5000?" o "ha iniciado sesión y además es administrador".

Los operadores de comparación (símbolos que examinan la relación entre dos valores; ===, visto antes en este artículo, es uno de ellos) sirven para comparar magnitudes, y los operadores lógicos (símbolos que combinan booleanos) encadenan varias condiciones.

Hay 4 operadores de comparación (> < >= <=) y su resultado es siempre true o false.

Operadores lógicos hay 3: && es true solo cuando ambos lados son true, || es true cuando lo es cualquiera de los dos lados y ! intercambia true y false.

Los 3 operadores lógicos
&&Solo cuandoambos son truetrue||Cuando cualquieraes truetrue!Invierte truey falseValor opuesto
&& estrecha una condición, || la amplía, y ! invierte el resultado.

La condición que construyes se le pasa a una sentencia if (una construcción que ejecuta el bloque siguiente solo cuando la condición entre paréntesis es true). Lo que debe ejecutarse cuando la condición es false va en el bloque que sigue a else.

Aquí lo usamos solo para confirmar el resultado de una condición: encadenar else if y ramificar con switch los veremos en el artículo de condicionales de la categoría de sintaxis.

const cartTotal = 4800;    // total del carrito
const hasCoupon = true;    // si el usuario tiene cupón
const isMember = false;    // si el usuario es socio

console.log(cartTotal >= 5000);   // false  no llega a 5000
console.log(cartTotal < 5000);    // true

console.log(hasCoupon && isMember);   // false  no es socio
console.log(hasCoupon || isMember);   // true   pero sí tiene cupón
console.log(!isMember);               // true   invierte false

if (cartTotal >= 5000) {
  console.log("Envío gratis");   // se ejecuta solo cuando la condición es true
} else {
  console.log(`Faltan ${5000 - cartTotal} para el envío gratis`);   // esto se ejecuta cuando es false
}

Cambia el menú que se muestra combinando el estado de la sesión con el indicador de administrador. isLoggedIn (si el usuario ha iniciado sesión) e isAdmin (si es administrador) ya están declaradas.

① Muestra si ha iniciado sesión y además es administrador.

② Muestra si ha iniciado sesión y no es administrador.

③ Solo cuando se cumple la condición de ②, muestra "Mi cuenta".

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Truthy y falsy — lo que if trata como falso

Los paréntesis de un if pueden contener valores distintos de true / false. Cuando ocurre, JavaScript interpreta ese valor como uno u otro.

Un valor que se interpreta como falso se llama falsy; todo lo demás es truthy (un valor que actúa como true dentro de una condición). Solo hay 6 valores falsy con los que te vas a encontrar en una condición, de modo que, si te aprendes esos 6, todo lo demás lo puedes tratar como truthy.

Los 6 son false, el número 0, la cadena vacía "", null (un valor puesto a propósito para indicar que no hay nada), undefined (un valor que indica que aún no se ha asignado nada) y NaN. En un artículo posterior veremos con detalle cuándo usar null y cuándo undefined.

En la práctica te encontrarás sobre todo con 0 y "", de manera que basta con tener presentes esos dos al principio. NaN es la excepción: devuelve false incluso al compararlo consigo mismo con ===, por lo que para comprobar si un valor es NaN se recurre a una forma de escribirlo específica.

Los 6 valores falsy
false0""cadena vacíanullundefinedNaN"0"cero como string" "un espacio-1número no ceroLos 6 valores falsyParecen falsy, pero son truthy
Las 2 filas superiores son todo lo falsy. Todo lo demás es truthy, incluidos los valores de la fila inferior que parecen 0 o vacíos pero no lo son.

Donde más se tropieza es con el número 0 y la cadena vacía.

Si el número de reseñas es 0, o el campo de búsqueda está vacío (""), pasar ese valor directamente a if hace que la condición no se cumpla. Lo que pretendías comprobar ("¿tiene algún valor?") acaba siendo otra cosa: "¿es distinto de cero y no está vacío?".

const reviewCount = 0;    // número de reseñas
const searchWord = "";    // texto escrito en el campo de búsqueda

if (reviewCount) {
  console.log("Tiene reseñas");
}
if (searchWord) {
  console.log("Tiene un término de búsqueda");
}
// 0 y una cadena vacía son ambos falsy, así que ninguna de las dos anteriores se ejecuta

if (reviewCount === 0) {
  console.log("Aún sin reseñas");   // esta sí se ejecuta
}

Deja explícita la condición cuando 0 es un valor con significado

En valores donde el propio 0 tiene significado, como unas existencias, un número de elementos o un importe, escribir if (stock) se salta el bloque justo cuando vale 0. Si dejas explícito lo que de verdad quieres comprobar, con stock > 0 o stock === 0, la intención queda clara también para quien lea el código.

Escribe el código que muestra las existencias en pantalla. mugStock, que está agotado, y bottleStock, que sí tiene existencias, ya están declaradas.

① Usando mugStock directamente como condición, escribe el código que mostraría una línea con las existencias incrustadas, del estilo de "Taza: quedan 5". Este paso sirve para ver qué ocurre: lo correcto es que esa línea NO se muestre.

② Usa bottleStock como condición de la misma forma y muestra sus existencias con el mismo formato.

③ Ramifica según si mugStock es mayor que 0: muestra "Taza: quedan X" si hay existencias y "Taza: sin existencias" si no.

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Evaluación de cortocircuito — fijar un valor por defecto con ||

Incluso un usuario que se registró sin escribir un nombre visible necesita ver algo en pantalla. Esa lógica de "usa un valor por defecto cuando no hay valor" se escribe en una línea con ||.

Funciona porque && y || no fabrican un booleano: devuelven tal cual el valor de uno de los dos lados. Cuando los combinas con valores true y false, el resultado sigue siendo true o false, de manera que no contradice nada de lo visto hasta ahora.

|| devuelve tal cual el valor de la izquierda si es truthy, y ni siquiera llega a evaluar el lado derecho. Solo cuando el izquierdo es falsy devuelve el valor de la derecha.

&& funciona al revés: si el izquierdo es falsy, devuelve ese valor izquierdo sin evaluar el derecho. Este comportamiento de "no mirar el lado derecho hasta que haga falta" se llama evaluación de cortocircuito (no evaluar el lado derecho cuando el izquierdo ya decide el resultado por sí solo).

|| devuelve un valor, no un booleano
"" || "Invitado"Izq. falsy→ devuelve der."Invitado""Alice" ||"Invitado"Izq. truthy→ devuelve izq."Alice"0 || 1000 también es falsy→ devuelve der.100
Si el izquierdo es truthy, se devuelve tal cual; el derecho solo se devuelve cuando el izquierdo es falsy. 0 también es falsy, por eso se sustituye por el lado derecho.
const nickname = "";   // se dejó en blanco

// || devuelve el lado derecho solo cuando el izquierdo es falsy
console.log(nickname || "Invitado");    // Invitado
console.log("Bob" || "Invitado");       // Bob  el lado derecho ni se evalúa

// && devuelve el valor izquierdo si es falsy, sin evaluar el derecho
console.log(0 && "en stock");   // 0
console.log(5 && "en stock");   // en stock

|| no basta cuando quieres conservar 0 o una cadena vacía

|| sustituye por el valor por defecto cualquier valor falsy, con lo cual también desaparecen los valores falsy que tienen significado, como un saldo de puntos de 0 o un "0" escrito por el usuario. Para aplicar el valor por defecto solo cuando el valor es null o undefined, se usa otro operador, ??, que veremos en el artículo 9.

Aplica valores por defecto a un nombre visible y a un saldo de puntos. guestName (en blanco), memberName (ya rellenado) y memberPoint (un saldo de puntos) ya están declaradas.

① Muestra un nombre visible que recurra a "Invitado" cuando guestName esté vacío.

② Muestra el mismo patrón aplicado a memberName.

③ Muestra el mismo patrón aplicado a memberPoint con un valor por defecto de 100.

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1¿Qué muestra console.log("0" === 0);?

Pregunta 2¿Cuál de estos no es falsy?

Pregunta 3¿Qué muestra console.log(0 || 100);?