Quelle est la différence entre (NaN! = NaN) et (NaN! == NaN)?

Tout d'abord, je veux mentionner que je sais comment fonctionne isNaN() et Number.isNaN() . Je lis The Definite Guide par David Flanagan et il donne un exemple pour savoir si la valeur est NaN :

 x !== x 

Cela se traduira par true si et seulement si x est NaN .

Mais maintenant, j'ai une question: pourquoi utilise-t-il une comparaison rigoureuse? Parce qu'il semble que

 x != x 

Se comporte de la même manière. Est-il sécuritaire d'utiliser les deux versions, ou je manque de certaines valeurs en JavaScript qui renverront true pour x !== x et false pour x != x ?

Tout d'abord, permettez-moi de souligner que NaN est une valeur très spéciale: par définition, ce n'est pas égal à lui-même. Cela provient de la norme IEEE-754 sur laquelle s'appuient les nombres JavaScript. La valeur "pas un nombre" n'est jamais égale à elle-même, même si les bits correspondent exactement. (Ceux-ci ne sont pas nécessairement dans IEEE-754, il permet de multiples valeurs différentes "pas un nombre".) C'est pourquoi cela arrive même; Toutes les autres valeurs dans JavaScript sont égales à elles-mêmes, NaN est tout simplement spécial.

… est-ce que je manque une certaine valeur dans JavaScript qui renverra true pour x! == x et faux pour x! = X?

Non, vous n'êtes pas. La seule différence entre !== et != Est que le dernier fera une contrainte de type si nécessaire pour que les types d'opérandes soient les mêmes. Dans x != x , les types d'opérandes sont identiques, et c'est exactement le même que x !== x .

Ceci est clair depuis le début de la définition de l' Opération d'égalité abstraite :

  1. ReturnIfAbrupt (x).
  2. ReturnIfAbrupt (y).
  3. Si Type (x) est identique à Type (y), alors

    Renvoie le résultat d'une comparaison Strict Equality x === y.

Les deux premières étapes sont la plomberie de base. Donc, en effet, la première étape de == est de voir si les types sont les mêmes et, dans l'affirmative, faire === place. != Et !== sont juste des versions négatives de cela.

Donc, si Flanagan est correct que seul NaN sera vrai pour x !== x , nous pouvons être sûrs qu'il est également vrai que seul NaN sera vrai pour x != x

Beaucoup de programmeurs JavaScript par défaut utilisent === et !== pour éviter certains pièges autour de la contrainte de type que font les opérateurs en vrac, mais il n'y a rien à lire dans l'utilisation de Flanagan de l'opérateur strict vs. loose dans ce cas.

Aux fins de NaN,! != Et !== faire la même chose.

Cependant, de nombreux programmeurs évitent == ou != En JavaScript. Par exemple, Douglas Crockford les considère comme les « mauvaises parties » de la langue JavaScript parce qu'ils se comportent de manière inattendue et confuse:

JavaScript a deux ensembles d'opérateurs d'égalité: === et !== , et leurs jumeaux == et != . Les bons fonctionnent de la façon dont vous vous attendez.

… Mon conseil est de ne jamais utiliser les jumeaux pervers. Au lieu de cela, utilisez toujours === et !== .

Juste pour l'amusement, permettez-moi de vous montrer un exemple artificiel où x n'est pas NaN mais les opérateurs se comportent différemment de toute façon. Premièrement définissez:

 Object.defineProperty( self, 'x', { get: function() { return self.y = self.y ? 0 : '0'; } } ); 

Ensuite nous avons

 x != x // false 

mais

 x !== x // true 

Je veux simplement souligner que NaN n'est pas la seule chose qui produit x !== x sans utiliser l'objet global. Il existe beaucoup de moyens intelligents pour déclencher ce comportement. Voici un utilisant getters:

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

Comme d'autres réponses le soulignent, == effectue le type coersion, mais dans comme dans d'autres langues et par la norme – NaN indique une défaillance de calcul, et pour de bonnes raisons n'est pas égal à lui-même.

Pour une raison quelconque au-delà de moi, les gens ont un problème avec JS, mais la plupart des langues qui ont des doubles (C, Java, C ++, C #, Python et autres) présentent ce comportement exact et les gens sont très bien avec elle.

Comme parfois, les images sont meilleures que les mots, vérifiez ce tableau (c'est la raison pour laquelle je fais une réponse plutôt qu'un commentaire, c'est parce qu'il obtient une meilleure visibilité).

Vous voyez que la comparaison stricte de l'égalité (===) ne revient que si le type et le contenu correspondent, donc

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

Bien que la comparaison de l'égalité abstraite (==) vérifie uniquement le contenu * en convertissant les types et en les comparant strictement:

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

Bien que ce ne soit pas clair, sans consulter ECMA , ce que JavaScript considère lors de la comparaison, de sorte que le code ci-dessous évalue comme vrai.

  var howAmISupposedToKnowThat = [] == false; //true