¿Cuál es la diferencia entre (NaN!= NaN) y (NaN!= = NaN)?


En primer lugar quiero mencionar que sé cómo funcionan isNaN() y Number.isNaN(). Estoy leyendo La Guía Definida de David Flanagan y él da un ejemplo de cómo comprobar 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 la comparación estricta? Porque parece que

x != x

Se comporta de la misma manera. Es seguro usar ambas versiones, o me faltan algunos valores en JavaScript que volverá true para x !== x y false para x != x?

Author: Chris Sprague, 2015-12-14

5 answers

Primero, permítanme señalar que NaN es un valor muy especial: Por definición, no es igual a sí mismo. Eso 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. (Que no están necesariamente en IEEE-754, permite múltiples valores diferentes de "no un número".) Por lo que esto incluso surge; todos los demás valores en JavaScript son iguales a sí mismos, NaN es simplemente especial.

Am ¡me falta algún valor en JavaScript que devolverá 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 los mismos. En x != x, los tipos de los operandos son los mismos, por lo que es exactamente igual que x !== x.

Esto está claro desde el principio de la definición de la Igualdad Abstracta Operación:

  1. ReturnIfAbrupt(x).
  2. ReturnIfAbrupt(y).
  3. Si Type(x) es el mismo que Type(y), entonces

    Devuelve el resultado de realizar una Comparación de Igualdad Estricta x = = = y.

  4. ...

Los dos primeros pasos son la plomería básica. Así, en efecto, el primer paso de == es ver si los tipos son los mismos y, si es así, hacer === en su lugar. != y !== simplemente se niegan versiones de eso.

Así que si Flanagan es correcto que solo NaN dará true para x !== x, podemos estar seguros de que también es cierto que solo NaN dará true para x != x.

Muchos programadores de JavaScript utilizan por defecto === y !== para evitar algunas trampas en torno a la coerción de tipos que hacen los operadores sueltos, pero no hay nada que leer en el uso de Flanagan del operador estricto vs.loose en este caso.

 125
Author: T.J. Crowder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 17:21:23

Para propósitos de NaN, != y !== hacen lo mismo.

Sin embargo, muchos programadores evitan == o != en JavaScript. Por ejemplo, Douglas Crockford los considera entre las "partes malas " 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.

My Mi consejo es nunca usar a los gemelos malvados. En su lugar, utilice siempre === y !==.

 37
Author: jkdev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-15 12:37:24

Solo por diversión, permítanme mostrarles 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
 22
Author: GOTO 0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-14 11:19:50

Solo quiero señalar que NaN no es lo único que produce x !== x sin usar el objeto global. Hay muchas maneras inteligentes de desencadenar este comportamiento. Aquí hay uno que usa getters:

var i = 0, obj = { get x() { return i++; }};
with(obj) // force dynamic context, this is evil. 
console.log(x === x); // false

Como señalan otras respuestas, == realiza coersión de tipo, pero en al igual que en otros lenguajes y par el estándar - NaN indica un fallo de cálculo, y por buenas razones no es igual a sí mismo.

Por alguna razón más allá de mí la gente ocnsider esto un problema con JS pero la mayoría los lenguajes que tienen dobles (a saber, C, Java, C++, C#, Python y otros) exhiben este comportamiento exacto y la gente está bien con él.

 2
Author: Benjamin Gruenbaum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-15 08:49:22

Como a veces, las imágenes son mejores que las palabras, revise esta tabla (que es la razón por la que hago esto una respuesta en lugar de un comentario es porque obtiene una mejor visibilidad).

Allí se puede ver que la comparación de igualdad estricta ( = = = ) solo devuelve true si el tipo y el contenido coinciden, por lo que

var f = "-1" === -1; //false

Mientras que abstract equality comparison ( = = ) comprueba solo el contenido * convirtiendo tipos y luego comparándolos estrictamente:

var t = "-1" == -1; //true

Aunque no está claro, sin consultar ECMA, lo que JavaScript considera al comparar, de una manera que el código de abajo se evalúa como verdadero.

 var howAmISupposedToKnowThat = [] == false; //true
 0
Author: MVCDS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 11:17:14