Conocemos muchos operadores de comparación de las matemáticas:
En Javascript se escriben así:
- Mayor/menor que:
a > b
,a < b
. - Mayor/menor o igual que:
a >= b
,a <= b
. - Igual:
a == b
(ten en cuenta que el doble signo==
significa comparación, mientras que un solo símboloa = b
significaría una asignación). - Distinto. En matemáticas la notación es
≠
, pero en JavaScript se escribe como una asignación con un signo de exclamación delante:a != b
.
En este artículo, aprenderemos más sobre los diferentes tipos de comparaciones y de cómo las realiza JavaScript, incluidas las peculiaridades importantes.
Al final, encontrará una buena receta para evitar problemas relacionadas con las “peculiaridades” de JavaScript.
Booleano es el resultado
Como todos los demás operadores, una comparación retorna un valor. En este caso, el valor es un booleano.
true
– significa “sí”, “correcto” o “verdad”.false
– significa “no”, “equivocado” o " no verdad".
Por ejemplo:
alert( 2 > 1 ); // true (correcto)
alert( 2 == 1 ); // false (incorrecto)
alert( 2 != 1 ); // true (correcto)
El resultado de una comparación puede asignarse a una variable, igual que cualquier valor:
let result = 5 > 4; // asignar el resultado de la comparación
alert( result ); // true
Comparación de cadenas
Para ver si una cadena es “mayor” que otra, JavaScript utiliza el llamado orden “de diccionario” o “lexicográfico”.
En otras palabras, las cadenas se comparan letra por letra.
Por ejemplo:
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
El algoritmo para comparar dos cadenas es simple:
- Compare el primer carácter de ambas cadenas.
- Si el primer carácter de la primera cadena es mayor (o menor) que el de la otra cadena, entonces la primera cadena es mayor (o menor) que la segunda. Hemos terminado.
- De lo contrario, si los primeros caracteres de ambas cadenas son los mismos, compare los segundos caracteres de la misma manera.
- Repita hasta el final de cada cadena.
- Si ambas cadenas tienen la misma longitud, entonces son iguales. De lo contrario, la cadena más larga es mayor.
En los ejemplos anteriores, la comparación 'Z' > 'A'
llega a un resultado en el primer paso.
La segunda comparación "Glow"
y "Glee"
necesitan más pasos, se comparan carácter por carácter:
G
es igual queG
.l
es igual quel
.o
es mayor quee
. Detente aquí. La primera cadena es mayor.
El algoritmo de comparación dado arriba es aproximadamente equivalente al utilizado en los diccionarios o guías telefónicas, pero no es exactamente el mismo.
Por ejemplo, las mayúsculas importan. Una letra mayúscula "A"
no es igual a la minúscula "a"
. ¿Cuál es mayor? La "a"
minúscula. ¿Por qué? Porque el carácter en minúsculas tiene un mayor índice en la tabla de codificación interna que utiliza JavaScript (Unicode). Volveremos a los detalles específicos y las consecuencias de esto en el capítulo Strings.
Comparación de diferentes tipos
Al comparar valores de diferentes tipos, JavaScript convierte los valores a números.
Por ejemplo:
alert( '2' > 1 ); // true, la cadena '2' se convierte en el número 2
alert( '01' == 1 ); // true, la cadena '01' se convierte en el número 1
Para valores booleanos, true
se convierte en 1
y false
en 0
.
Por ejemplo:
alert( true == 1 ); // true
alert( false == 0 ); // true
Es posible que al mismo tiempo:
- Dos valores sean iguales.
- Uno de ellos sea
true
como booleano y el otro seafalse
como booleano.
Por ejemplo:
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert( a == b ); // true!
Desde el punto de vista de JavaScript, este resultado es bastante normal. Una comparación de igualdad convierte valores utilizando la conversión numérica (de ahí que "0"
se convierta en 0
), mientras que la conversión explícita Boolean
utiliza otro conjunto de reglas.
Igualdad estricta
Una comparación regular de igualdad ==
tiene un problema. No puede diferenciar 0
de `falso’:
alert( 0 == false ); // true
Lo mismo sucede con una cadena vacía:
alert( '' == false ); // true
Esto sucede porque los operandos de diferentes tipos son convertidos a números por el operador de igualdad ==
. Una cadena vacía, al igual que false
, se convierte en un cero.
¿Qué hacer si queremos diferenciar 0
de false
?
Un operador de igualdad estricto ===
comprueba la igualdad sin conversión de tipo.
En otras palabras, si a
y b
son de diferentes tipos, entonces a === b
retorna inmediatamente false
sin intentar convertirlos.
Intentémoslo:
alert( 0 === false ); // falso, porque los tipos son diferentes
Existe también un operador de “diferencia estricta” !==
análogo a !=
.
El operador de igualdad estricta es un poco más largo de escribir, pero hace obvio lo que está pasando y deja menos espacio a errores.
Comparación con nulos e indefinidos
Veamos más casos extremos.
Hay un comportamiento no intuitivo cuando se compara null
o undefined
con otros valores.
- Para un control de igualdad estricto
===
-
Estos valores son diferentes, porque cada uno de ellos es de un tipo diferente.
alert( null === undefined ); // false
- Para una comparación no estricta
==
-
Hay una regla especial. Estos dos son una " pareja dulce ": son iguales entre sí (en el sentido de
==
), pero no a ningún otro valor.alert( null == undefined ); // true
- Para matemáticas y otras comparaciones
< > <= >=
-
null/undefined
se convierten en números:null
se convierte en0
, mientras queundefined
se convierte enNaN
.
Ahora veamos algunos hechos graciosos que suceden cuando aplicamos estas reglas. Y, lo que es más importante, cómo no caer en una trampa con ellas.
Resultado extraño: null vs 0
Comparemos null
con un cero:
alert( null > 0 ); /// (1) false
alert( null == 0 ); /// (2) false
alert( null >= 0 ); // (3) true
Matemáticamente, eso es extraño. El último resultado afirma que “null
es mayor o igual a cero”, así que en una de las comparaciones anteriores debe ser true
, pero ambas son falsas.
La razón es que una comparación de igualdad ==
y las comparaciones > < >= <=
funcionan de manera diferente. Las comparaciones convierten a null
en un número, tratándolo como 0
. Es por eso que (3) null >= 0
es verdadero y (1) null > 0
es falso.
Por otro lado, el control de igualdad ==
para undefined
y null
se define de tal manera que, sin ninguna conversión, son iguales entre sí y no son iguales a nada más. Es por eso que (2) null == 0
es falso.
Un indefinido incomparable
El valor undefined
no debe compararse con otros valores:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
¿Por qué le desagrada tanto el cero? ¡Siempre falso!
Obtenemos estos resultados porque:
- Las comparaciones
(1)
y(2)
retornanfalso
porqueno definido
se convierte enNaN
yNaN
es un valor numérico especial que retornafalso
para todas las comparaciones. - La comparación de igualdad
(3)
retornafalso
porqueundefined
sólo equivale anull
y a ningún otro valor.
Evitar los problemas
¿Por qué repasamos estos ejemplos? ¿Deberíamos recordar estas peculiaridades todo el tiempo? Bueno, en realidad no. De hecho, estas peculiaridades se volverán familiares con el tiempo, pero hay una manera sólida de evadir los problemas con ellas:
-
Trata cualquier comparación con
undefined/null
(excepto la igualdad estricta===
) con sumo cuidado. -
No uses comparaciones
>= > < <=
con una variable que puede sernull/undefined
, a menos que estés realmente seguro de lo que estás haciendo. Si una variable puede tener estos valores, verifícalos por separado.
Resumen
- Los operadores de comparación retornan un valor booleano.
- Las cadenas se comparan letra por letra en el orden del “diccionario”.
- Cuando se comparan valores de diferentes tipos, se convierten en números (excepto un control de igualdad estricta).
- Los valores
null
yundefined
son iguales==
entre sí y no equivalen a ningún otro valor. - Ten cuidado al usar comparaciones como
>
o<
con variables que ocasionalmente pueden sernull/undefined
. Revisar por separado si haynull/undefined
es una buena idea.
Comentarios
<code>
, para varias líneas – envolverlas en la etiqueta<pre>
, para más de 10 líneas – utilice una entorno controlado (sandbox) (plnkr, jsbin, codepen…)