javascript - ¿Cuál es la diferencia entre (NaN != NaN) y (NaN !== NaN)?
Primero que nada quiero mencionar que sé cómo funcionan isNaN() y Number.isNaN(). Estoy leyendo The Definite Guide de David Flanagan y él da un ejemplo de cómo verificar si el valor es NaN:
x !== x
Esto resultará en true si y solo si x es NaN.
Pero ahora tengo una pregunta: ¿por qué usa comparación estricta? Porque parece que
x != x
se comporta de la misma manera. ¿Es seguro usar ambas versiones, o me estoy perdiendo algún valor en JavaScript que devuelva true para x !== x y false para x != x?
Respuesta #1
Primero, permítanme señalar que NaN es un valor muy especial: por definición, no es igual a sí mismo. Esto proviene del estándar IEEE-754 en el que se basan los números de JavaScript. El valor "no es un número" nunca es igual a sí mismo, incluso cuando los bits coinciden exactamente. (Cosa que no necesariamente ocurre en IEEE-754, ya que permite múltiples valores diferentes de "no es un número".) Por eso surge esto; todos los demás valores en JavaScript son iguales a sí mismos, NaN es simplemente especial.
...¿me estoy perdiendo algún valor en JavaScript que devuelva true para x !== x y false para x != x?
No, no lo eres. La única diferencia entre !== y != es que este último hará coerción de tipos si es necesario para que los tipos de los operandos sean iguales. En x != x, los tipos de los operandos son iguales, por lo que es exactamente lo mismo que x !== x.
Esto queda claro desde el comienzo de la definición de la Operación de Igualdad Abstracta:
- DevuelveSiAbrupto(x).
- DevuelveSiAbrupto(y).
Si Type(x) es el mismo que Type(y), entonces
Devuelve el resultado de realizar la Comparación de Igualdad Estricta x === y.
...
Los dos primeros pasos son plomería básica. Así que, en efecto, el primer paso de == es ver si los tipos son iguales y, si es así, hacer === en su lugar. != y !== son solo versiones negadas de eso.
Así que si Flanagan tiene razón en que solo NaN dará verdadero para x !== x, podemos estar seguros de que también es cierto que solo NaN dará verdadero para x != x.
Muchos programadores de JavaScript optan por usar === y !== para evitar algunos problemas relacionados con la coerción de tipos que hacen los operadores laxos, pero no hay nada que interpretar en el uso de operadores estrictos frente a laxos de Flanagan en este caso.
Respuesta #2
Para los propósitos de NaN, != y !== hacen lo mismo.
Sin embargo, muchos programadores evitan == o != en JavaScript. Por ejemplo, Douglas Crockford los considera entre las "malas partes" del lenguaje JavaScript porque se comportan de maneras inesperadas y confusas:
JavaScript tiene dos conjuntos de operadores de igualdad:
===y!==, y sus gemelos malvados==y!=. Los buenos funcionan de la manera que esperarías....Mi consejo es no usar nunca a los gemelos malvados. En su lugar, siempre usa
===y!==.
Respuesta #3
Solo por diversión, déjame mostrarte un ejemplo artificial donde x no es NaN pero los operadores se comportan de manera diferente de todos modos. Primero define:
Object.defineProperty(
self,
'x',
{ get: function() { return self.y = self.y ? 0 : '0'; } }
);
Entonces tenemos
x != x // false
pero
x !== x // true
