Giorgi Nakeuri
Antes que nada quiero mencionar que sé cómo isNaN()
y Number.isNaN()
trabajar. Estoy leyendo La guía definitiva por David Flanagan y 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 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 devolverán true
por x !== x
y false
por x != x
?
TJ Crowder
En primer lugar, 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 “no un número”). Es por eso que incluso surge esto; todos los demás valores en JavaScript son iguales a ellos mismos, NaN
es simplemente especial.
… ¿me falta algún valor en JavaScript que devolverá verdadero para x !== x y falso para x != x?
No tu no 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 lo mismo que x !== x
.
Esto queda claro desde el comienzo de la definición de la Operación de igualdad abstracta:
- Devolver si es abrupto (x).
- ReturnIfAbrupt(y).
Si Tipo(x) es lo mismo que Tipo(y), entonces
Devuelve el resultado de realizar la Comparación de igualdad estricta x === y.
…
Los primeros dos pasos son plomería básica. Entonces, en efecto, el primer paso de ==
es ver si los tipos son los mismos y, si es así, hacer ===
en cambio. !=
y !==
son solo versiones negadas de eso.
Entonces, si Flanagan tiene razón en que solo NaN
dará verdad por x !== x
podemos estar seguros de que también es cierto que sólo NaN
dará verdad para x != x
.
Muchos programadores de JavaScript usan por defecto ===
y !==
para evitar algunas trampas en torno al tipo de coerción que hacen los operadores flexibles, pero no hay nada que leer en el uso de Flanagan del operador estricto frente al operador flexible en este caso.
-
he releído
4.9.1 - Equality and Inequality Operators
y esta parece ser la respuesta. El punto clave para===
la comparación es:If the two values have the same type, test them for strict equality as described above. If they are strictly equal, they are equal. If they are not strictly equal, they are not equal
.– Giorgi Nakeuri
14 de diciembre de 2015 a las 9:27
-
@GiorgiNakeuri: No estoy seguro de a qué 4.9.1 te refieres, ¿quizás al libro de Flanagan? Pero eso básicamente dice lo que dice la cita de la especificación anterior, sí.
–TJ Crowder
14 de diciembre de 2015 a las 9:32
-
Acepto esto porque responde a mi pregunta de manera formal y precisa. ¡Gracias por las explicaciones!
– Giorgi Nakeuri
14 de diciembre de 2015 a las 10:01
-
@Moshe: ¿Qué quiere decir con “enlaces en vivo”? (El término no aparece en la especificación). ¿Quiere decir algo como el ejemplo de GOTO 0 donde
a
es en realidad una función y no devuelve el mismo valor dos veces? Eso no es lo mismo que un valor para cual!==
sería cierto, que es lo que preguntó el OP. Es solo una función que devuelve diferentes valores.foo() !== foo()
tampoco es necesariamente cierto, ya quefoo
podría devolver valores diferentes en cada llamada.–TJ Crowder
14/12/2015 a las 18:30
-
@Moshe Bueno, esa es una forma súper desagradable de meterse con propiedades y captadores. Pero parece ser más o menos lo mismo que el ejemplo de GOTO 0, solo con una capa adicional de direccionamiento indirecto.
– JAB
14 de diciembre de 2015 a las 21:18
jkdev
A efectos de NaN, !=
y !==
hacer la misma cosa.
Sin embargo, muchos programadores evitan ==
o !=
en JavaScript. Por ejemplo, Douglas Crockford los considera entre los “partes malas” del lenguaje JavaScript porque se comportan de formas inesperadas y confusas:
JavaScript tiene dos conjuntos de operadores de igualdad:
===
y!==
y sus gemelos malvados==
y!=
. Los buenos funcionan como cabría esperar.… Mi consejo es nunca usar a los gemelos malvados. En su lugar, utilice siempre
===
y!==
.
-
La pregunta no es sobre NaN (a pesar del título). La pregunta es “¿Me estoy perdiendo algún valor en JavaScript que devolverá verdadero para x! == x y falso para x! = x?”
–TJ Crowder
14 de diciembre de 2015 a las 9:12
-
@TJCrowder Dos preguntas, de verdad. La primera pregunta es “¿Es seguro usar ambas versiones?” y la respuesta es que ambas versiones son equivalentes. Me gusta su respuesta “bajo el capó” que explica todo en detalle.
– jkdev
14 de diciembre de 2015 a las 10:08
IR A 0
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
-
¡Decir ah! 🙂 Pero eso es efectivamente
foo() != foo()
donde foo devuelve 1 y luego 2. Por ejemplo, el valores no son lo mismo, es solo comparar diferentes valores.–TJ Crowder
14 de diciembre de 2015 a las 10:09
solo quiero señalar NaN
no es lo único que produce x !== x
sin utilizar el objeto global. Hay muchas formas inteligentes de desencadenar este comportamiento. Aquí hay uno que usa captadores:
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 coerción de tipos, pero al igual que en otros lenguajes y a la par del estándar, NaN indica una falla de cálculo y, por buenas razones, no es igual a sí mismo.
Por alguna razón más allá de mí, la gente considera que esto es un problema con JS, pero la mayoría de los lenguajes que tienen dobles (es decir, C, Java, C ++, C #, Python y otros) exhiben este comportamiento exacto y la gente está de acuerdo con eso.
Como a veces, las imágenes son mejores que las palabras, mira esto mesa (que es la razón por la que hago de esto una respuesta en lugar de un comentario porque tiene una mejor visibilidad).
Allí puede ver que la comparación de igualdad estricta (===) solo devuelve verdadero si el tipo y el contenido coinciden, por lo que
var f = "-1" === -1; //false
Mientras que la comparación de igualdad abstracta (==) verifica solo el contenido* al convertir tipos y luego compararlos estrictamente:
var t = "-1" == -1; //true
Aunque no está claro, sin consultar ECMAlo que JavaScript considera al comparar, de manera que el siguiente código se evalúe como verdadero.
var howAmISupposedToKnowThat = [] == false; //true
Podría ser que Flanagan simplemente prefiera
!==
revisa!=
cheques Hasta donde yo sé, no hay otro valor dondex != x
. Pero hay dos grupos distintos de desarrolladores de JavaScript: aquellos que prefieren!=
y los que prefieren!==
ya sea por rapidez, claridad, expresividad, etc.– Steve Klösters
14 de diciembre de 2015 a las 7:56
¿Por qué usar la comparación flexible cuando la comparación estricta se comporta de la misma manera?
– Ry-
♦
14 de diciembre de 2015 a las 8:06
@Rauluco:
NaN
no es un tipo único, es un número. es unico valor que no es igual a si mismo.–TJ Crowder
14 de diciembre de 2015 a las 9:15
El título parece estar engañando a la gente. Sugeriría cambiarlo a algo como “¿Es x != x alguna vez diferente de x !== x?”
–TJ Crowder
14 de diciembre de 2015 a las 9:16
@femmestem: Giorgi dijo “en este caso” es una cuestión de estilo. Y tiene razón en eso. Eso no es estilo cuando los tipos de los operandos son diferentes, pero es estilo cuando son iguales. Por separado: Flanagan está haciendo esas comparaciones con
===
con NaN para hacer el punto que NaN no es igual a sí mismo. No está “equivocado”, lo está haciendo como un ejercicio de enseñanza, demostrando que no funciona.–TJ Crowder
14 de diciembre de 2015 a las 9:39