Command Palette

Search for a command to run...

Operadores de Comparación e Igualdad en JavaScript

Entiende la comparación de valores con ===, ==, >, <, >=, <=. Aprende por qué === es más seguro que ==, y evita bugs comunes de comparación.

Lectura: 13 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • === (igualdad estricta) compara valor Y tipo sin coerción. == (igualdad suelta) hace coerción de tipos
  • SIEMPRE usa === y !== en lugar de == y != para evitar bugs de coerción inesperada
  • Operadores relacionales: > < >= <= comparan números. Con strings, comparan alfabéticamente (Unicode)
  • null == undefined es true, pero null === undefined es false. Son los únicos valores == sin ser ===
  • Objetos y arrays se comparan por referencia, no por contenido. {} === {} es false (referencias diferentes)
  • NaN no es igual a nada, ni a sí mismo: NaN === NaN es false. Usa Number.isNaN() para verificar NaN
  • Object.is() es como === pero distingue -0 de +0, y considera NaN === NaN true

Introducción a Operadores de Comparación

Los operadores de comparación permiten comparar dos valores y retornan un booleano (true o false). JavaScript tiene operadores de igualdad (===, ==, !==, !=) que verifican si dos valores son iguales o diferentes, y operadores relacionales (>, <, >=, <=) que verifican orden o magnitud. Estos operadores son fundamentales para condiciones, validaciones, y control de flujo en tu código.

La distinción más importante es entre igualdad estricta (===) e igualdad suelta (==). La igualdad estricta compara valor Y tipo sin hacer conversiones: 5 === "5" es false porque son tipos diferentes. La igualdad suelta hace coerción de tipos antes de comparar: 5 == "5" es true porque convierte el string a número. Esta coerción causa bugs sutiles, por eso la mejor práctica universal es SIEMPRE usar === y nunca usar ==.

Por Qué Existen Dos Tipos de Igualdad

JavaScript heredó == de lenguajes antiguos donde la coerción automática era común. === se añadió después para permitir comparación sin coerción, más predecible. Hoy en día, == se considera un error de diseño histórico: casi nunca quieres comparación con coerción. En JavaScript moderno, trata == como obsoleto y usa === siempre.

Igualdad Estricta (===): Sin Coerción

El operador de igualdad estricta (===) compara dos valores sin hacer conversión de tipos. Retorna true solo si ambos valores tienen el mismo tipo Y el mismo valor. 5 === 5 es true, pero 5 === "5" es false porque son tipos diferentes. También existe !== que retorna true si los valores son diferentes en valor O en tipo. Esta es la forma segura y predecible de comparar valores.

igualdad-estricta.js
Loading code...

Con ===, los valores deben ser del mismo tipo y tener el mismo valor para ser iguales. Números se comparan por valor, strings por contenido carácter por carácter, booleanos por valor. null solo es === a null, undefined solo es === a undefined. NaN no es === a nada, ni siquiera a sí mismo. Objetos y arrays se comparan por referencia: dos objetos con mismo contenido no son === si son instancias diferentes.

=== Es La Forma Correcta de Comparar

La mejor práctica universal en JavaScript moderno es SIEMPRE usar === y !== para comparaciones. Son más rápidos (sin coerción), más predecibles, y previenen bugs sutiles. Si quieres verificar null O undefined juntos, usa explícitamente: value === null || value === undefined. ESLint te avisará si usas ==. Trata === como el único operador de igualdad que existe.

Igualdad Suelta (==): Con Coerción

El operador de igualdad suelta (==) compara dos valores después de convertirlos a un tipo común. JavaScript tiene reglas complejas de coerción para ==: strings se convierten a números, booleanos se convierten a números (true es 1, false es 0), null == undefined es true por regla especial. Estas conversiones automáticas causan comportamientos contraintuitivos y bugs sutiles. Por eso == se considera mala práctica y debes evitarlo.

igualdad-suelta.js
Loading code...

El operador == hace coerción con reglas complejas: si los tipos son iguales, compara como ===; null == undefined es true, pero no son == a otros valores; si uno es número y otro string, convierte el string a número; si uno es boolean, lo convierte a número (true=1, false=0); y los objetos se convierten con valueOf() o toString(). Estas reglas causan resultados sorprendentes como "0" == false siendo true. Evita == completamente.

Por Qué == Es Peligroso

Las reglas de coerción de == son tan complejas que incluso programadores experimentados se equivocan. "0" == false es true, "0" == 0 también es true, y false == 0 es true, pero además [] == false es true. Estos comportamientos inconsistentes causan bugs difíciles de detectar. No hay ventaja en usar ==: solo añade complejidad y riesgo. Usa === siempre.

=== vs ==: Diferencias Clave y Cuándo Usar Cada Uno

La diferencia fundamental es que === compara sin coerción de tipos, mientras == hace coerción antes de comparar. === es más estricto, más rápido, más predecible. == es más permisivo pero impredecible. En código profesional moderno, se usa === exclusivamente. El único caso histórico donde algunos usan == es para verificar null y undefined juntos (value == null), pero incluso esto es mejor hacerlo explícitamente con === y ||.

estricta-vs-suelta.js
Loading code...

Diferencias principales entre === y ==:

  1. <code>===</code> compara tipo y valor; <code>==</code> solo valor después de coerción
  2. <code>===</code> es más rápido (sin conversiones); <code>==</code> es más lento
  3. <code>===</code> es predecible; <code>==</code> tiene reglas de coerción complejas
  4. <code>===</code> nunca causa bugs de coerción; <code>==</code> es fuente común de bugs
  5. <code>===</code> es el estándar en código moderno; <code>==</code> se considera obsoleto

Operadores Relacionales: >, <, >=, <=

Los operadores relacionales (>, <, >=, <=) verifican si un valor es mayor, menor, mayor o igual, o menor o igual que otro. Con números, funcionan como esperarías: 10 > 5 es true. Con strings, comparan alfabéticamente usando valores Unicode: "b" > "a" es true. Si comparas tipos diferentes, JavaScript hace coerción a número, lo que puede dar resultados inesperados.

operadores-relacionales.js
Loading code...

Los operadores relacionales funcionan bien con números. Con strings, comparan carácter por carácter usando valores Unicode (case-sensitive: "A" < "a" porque mayúsculas tienen códigos menores). Si comparas número con string, convierte a número: "10" > 5 es true. >= y <= combinan comparación con igualdad: 5 >= 5 es true. Con tipos mixtos, la coerción puede dar resultados inesperados: valida tipos antes de comparar.

Comparación de Strings: Unicode, No Alfabética

Los strings se comparan por código Unicode, no alfabéticamente: "Z" < "a" es true (mayúsculas antes que minúsculas). Para comparación case-insensitive, usa .toLowerCase(): str1.toLowerCase() > str2.toLowerCase(). Para comparación localizada (con acentos, ñ, etc.), usa localeCompare(): str1.localeCompare(str2). Unicode hace que "10" < "2" sea true (compara carácter por carácter: "1" < "2").

Comparación de Strings: Unicode y Casos Especiales

La comparación de strings en JavaScript se basa en valores Unicode (UTF-16), no en orden alfabético tradicional. Cada carácter tiene un código numérico, y la comparación se hace carácter por carácter de izquierda a derecha. Esto causa comportamientos inesperados: mayúsculas vienen antes que minúsculas, números como strings se ordenan lexicográficamente (no numéricamente), y caracteres especiales tienen posiciones específicas en la tabla Unicode.

comparacion-strings.js
Loading code...

Los strings se comparan carácter por carácter usando códigos Unicode. Mayúsculas (65-90) vienen antes que minúsculas (97-122), por eso "Z" < "a" es true. Números como strings se comparan lexicográficamente: "10" < "2" porque compara primero "1" vs "2". Para comparación case-insensitive, convierte a minúsculas con .toLowerCase(). Para comparación numérica, usa Number(). Para comparación localizada (alfabetos con acentos), usa localeCompare().

Comparación de Objetos: Por Referencia, No por Contenido

Los objetos y arrays se comparan por referencia, no por contenido. Dos objetos son iguales solo si son la MISMA instancia (apuntan a la misma ubicación en memoria). Dos objetos con propiedades idénticas no son === si son instancias diferentes. Esto es diferente a primitivos que se comparan por valor. Para comparar contenido de objetos, necesitas comparación profunda manual.

comparacion-objetos.js
Loading code...

Objetos y arrays se comparan por referencia. {} === {} es false porque son dos instancias diferentes, aunque tengan el mismo contenido. Solo si dos variables apuntan al MISMO objeto son ===. Esto aplica a arrays, funciones, fechas, y cualquier objeto. Para comparar contenido de objetos simples, JSON.stringify() puede funcionar como solución rápida, pero falla con funciones, undefined, símbolos, y si las propiedades están en distinto orden.

Casos Especiales: NaN, null, undefined, -0

JavaScript tiene varios casos especiales en comparaciones que pueden causar confusión. NaN (Not a Number) no es igual a nada, ni siquiera a sí mismo: NaN === NaN es false. null y undefined son == pero no ===. -0 y +0 son === aunque sean valores diferentes. Infinity es === a Infinity. Estos casos especiales requieren métodos específicos de verificación.

casos-especiales.js
Loading code...

Los casos especiales más importantes que debes conocer son:

  1. <code>NaN === NaN</code> es <code>false</code>: usa <code>Number.isNaN()</code> para verificar NaN
  2. <code>null == undefined</code> es <code>true</code>, pero <code>null === undefined</code> es <code>false</code>
  3. <code>-0 === +0</code> es <code>true</code> aunque matemáticamente sean diferentes
  4. <code>Infinity === Infinity</code> es <code>true</code>
  5. Objetos vacíos nunca son iguales: <code>&#123;&#125; === &#123;&#125;</code> es <code>false</code>

NaN: El Valor Que No Se Iguala a Sí Mismo

NaN es único porque no es igual a nada, ni a sí mismo: NaN === NaN retorna false. Esto viene de la especificación IEEE 754 para números flotantes. No puedes usar === para verificar NaN: debes usar Number.isNaN(valor). El método global isNaN() es diferente y menos confiable: convierte a número primero, así que isNaN("hola") es true. Usa Number.isNaN() que solo retorna true para NaN real.

Object.is(): Comparación Más Estricta que ===

Object.is() es un método moderno (ES6) que hace comparación similar a === pero con dos diferencias: distingue +0 de -0 (Object.is(+0, -0) es false), y considera NaN igual a NaN (Object.is(NaN, NaN) es true). Es la comparación más estricta y matemáticamente correcta de JavaScript. Úsalo cuando necesites distinguir estos casos edge, pero para la mayoría de comparaciones === es suficiente.

object-is.js
Loading code...

Object.is() es como === pero más correcto matemáticamente: distingue +0 de -0 (mientras === los trata como iguales), y considera NaN === NaN como true (mientras === lo trata como false). En todo lo demás funciona igual que ===. Úsalo cuando estos casos edge importan (cálculos científicos, claves de Map). Para comparaciones normales, === es suficiente. Object.is() no hace coerción de tipos como ==.

Resumen: Operadores de Comparación

Operadores principales:

  • === !== para igualdad estricta sin coerción (SIEMPRE usa estos)
  • == != para igualdad suelta con coerción (NUNCA uses estos)
  • > < >= <= para comparar magnitud de números y orden de strings
  • Object.is() para comparación perfecta que distingue +0/-0 y NaN
  • Objetos se comparan por referencia, no por contenido

Mejores prácticas:

  • SIEMPRE usa === y !==, NUNCA uses == o !=
  • Para NaN usa Number.isNaN(), no comparación directa
  • Para null/undefined usa === null o === undefined explícitamente
  • Strings se comparan por Unicode, usa localeCompare() para alfabético
  • Para comparar objetos por contenido, usa comparación manual o JSON.stringify()