web-dev-qa-db-fra.com

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

Tout d'abord, je tiens à mentionner que je sais comment fonctionnent isNaN() et Number.isNaN(). Je lis The Definite Guide par David Flanagan et il donne un exemple sur la manière de vérifier si la valeur est NaN:

x !== x

Cela aura pour résultat true si et seulement si x est NaN.

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

x != x

se comporte de la même manière. Est-il prudent d’utiliser les deux versions, ou il me manque des valeurs en JavaScript qui renverront true pour x !== x et false pour x != x?

147
Giorgi Nakeuri

Tout d’abord, permettez-moi de souligner que NaN est une valeur très spéciale: par définition, elle n’est pas égale à elle-même. Cela provient de la norme IEEE-754 à laquelle les chiffres JavaScript s’appuient. La valeur "pas un nombre" n'est jamais égale à elle-même, même lorsque les bits correspondent exactement. (Ce qu'ils ne font pas nécessairement dans IEEE-754, cela permet plusieurs valeurs différentes "pas un nombre".) C'est pourquoi cela se produit même; toutes les autres valeurs en JavaScript sont égales à elles-mêmes, NaN est tout simplement spécial.

... il me manque une valeur dans JavaScript qui renvoie true pour x! == x et false pour x! = x?

Non, tu ne l'es pas. La seule différence entre !== et != est que ce dernier fera la coercition de type si nécessaire pour que les types d'opérandes soient identiques. Dans x != x, les types d’opérandes sont les mêmes et sont donc exactement les mêmes que x !== x.

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

  1. ReturnIfAbrupt (x).
  2. ReturnIfAbrupt (y).
  3. Si le type (x) est identique au type (y), alors

    Renvoie le résultat de la comparaison stricte d'égalité x === y.

  4. ...

Les deux premières étapes sont la plomberie de base. Donc, en effet, la toute première étape de == est de voir si les types sont les mêmes et, si oui, de faire === au lieu. != et !== ne sont que des versions annulées de cela.

Donc, si Flanagan a raison, seul NaN donnera vrai pour x !== x, nous pouvons être sûrs que c’est également vrai que seul NaN donnera vrai pour x != x.

De nombreux programmeurs JavaScript utilisent par défaut === et !== pour éviter certains écueils liés à la coercition de types exercée par les opérateurs peu scrupuleux, mais rien n’indique que Flanagan ait utilisé l’opérateur strict vs non attaché dans ce cas.

127
T.J. Crowder

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

Cependant, beaucoup de programmeurs évitent == ou != en JavaScript. Par exemple, Douglas Crockford les considère comme l'un des " mauvaises parties " du langage JavaScript, car ils se comportent de manière inattendue et source de confusion:

JavaScript possède deux ensembles d'opérateurs d'égalité: === et !==, et leurs jumeaux diaboliques == et !=. Les bons fonctionnent comme vous le souhaiteriez.

... Mon conseil est de ne jamais utiliser les jumeaux maléfiques. Au lieu de cela, utilisez toujours === et !==.

37
jkdev

Juste pour le plaisir, laissez-moi vous montrer un exemple artificiel où x n'est pas NaN mais les opérateurs se comportent différemment de toute façon. D'abord définir:

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

Ensuite nous avons

x != x // false

mais

x !== x // true
22
GOTO 0

Je veux juste souligner que NaN n’est pas la seule chose qui produit x !== x sans utiliser l'objet global. Il y a beaucoup de façons intelligentes de déclencher ce comportement. En voici un en utilisant des getters:

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

Comme le soulignent d’autres réponses, == effectue la coersion de types, mais comme dans d’autres langages et conformément à la norme - NaN indique un échec de calcul et, pour de bonnes raisons, n’est pas égal à lui-même.

Pour une raison quelconque, au-delà de moi, les gens pensent que c'est un problème avec JS, mais la plupart des langages qui ont des doubles (à savoir, C, Java, C++, C #, Python et d'autres)) présentent ce comportement exact et les personnes ne sont que d'accord avec ça.

2
Benjamin Gruenbaum

Comme parfois, les images valent mieux que les mots, cochez table (ce qui me permet d’en faire une réponse plutôt qu’un commentaire, c’est parce que cela donne une meilleure visibilité).

Vous pouvez voir que la comparaison d’égalité stricte (===) ne renvoie vrai que si le type et le contenu correspondent, donc

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

Alors que la comparaison d'égalité abstraite (==) vérifie uniquement le contenu * en convertissant les types puis en les comparant strictement:

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

Bien que ce ne soit pas clair, sans consultation ECMA , ce que JavaScript prend en compte lors de la comparaison, de manière à ce que le code ci-dessous soit évalué à true.

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