web-dev-qa-db-fra.com

Comment testez-vous NaN en JavaScript?

J'ai une variable x et je veux tester si x est défini sur NaN. Comment je fais ça?

Mon premier instinct est probablement, vous savez, de le tester, comme ceci:

if (x === NaN) {  ...

Lapin idiot, non, ce serait beaucoup trop facile. NaN est comme NULL en SQL, il n’est égal à rien, pas même à lui-même.

Mais regardez, il y a une fonction appelée isNaN() - peut-être que ça va le faire!

Non, pour autant que je sache, isNaN() ne vaut absolument rien.

Par exemple, isNaN([""]) renvoie correctement false, mais isNaN(["."]) renvoie true. Vous ne voulez pas savoir comment j'ai appris à propos de cette faille.

Comment puis-je faire cela?

Il se trouve que ma question est une copie de celle-ci , mais la réponse sélectionnée est fausse. Le bonne réponse compte 20% de votes positifs en plus.

37
Malvolio

La question a la réponse si vous lisez assez attentivement. C'est ainsi que je l'ai trouvé: je dactylographiais la question et ... du bingo.

Vous vous souvenez quand j'ai écrit "NaN est comme NULL en SQL, il n'est égal à rien, même lui-même"? Autant que je sache, NaN est la seule valeur en Javascript avec cette propriété. Par conséquent, vous pouvez écrire:

var reallyIsNaN = function(x) {
   return x !== x;
};
22
Malvolio

Réponse courte

Pour les utilisateurs ECMAScript-5:

#1
if(x !== x) {
    console.info('x is NaN.');
}
else {
    console.info('x is NOT a NaN.');
}

Pour les personnes utilisant ECMAScript-6:

#2
Number.isNaN(x);

Et par souci de cohérence entre ECMAScript 5 et 6, vous pouvez également utiliser ceci polyfill pour Number.isNan

#3
//Polyfill from MDN
Number.isNaN = Number.isNaN || function(value) {
    return typeof value === "number" && isNaN(value);
}
// Or
Number.isNaN = Number.isNaN || function(value) {     
    return value !== value;
}

Remarque: je préfère tester avec # 1, qui fonctionne de la même manière dans tous les lieux et ne dépend pas non plus du dernier JS. (Cela me donne toujours un résultat correct. Pas de surprises!)


Explication détaillée:

Voici notre génial NaN

NaN == NaN; // false
NaN === NaN; // false

S'il vous plaît, ne blâmez pas JavaScript pour cela, c'est NaN qui est supposé se comporter de cette manière dans d'autres langues également. Ce qui est correct, comme dans justification de toutes les comparaisons renvoyant de fausses valeurs NaN

Vient donc isNaN comme notre sauveur, mais attendez que cela agisse de façon très différente dans certains scénarios comme

isNaN(undefined); // true
isNaN({});        // true
isNaN("lorem ipsum"); // true

J'ai eu des visages étranges en voyant les résultats ci-dessus. Et voici la raison de MDN

Lorsque l'argument de la fonction isNaN n'est pas de type Number, la valeur est d'abord contrainte à un nombre. La valeur résultante est ensuite testée pour déterminer s'il s'agit de NaN.

Alors, comment devrions-nous tester NaN pour les variables non numériques? Je passe toujours par le suivant

if(x !== x) {
    console.info('Is a NaN');
}
else {
    console.info('Not a NaN');
}

Mises à jour ECMAScript-6/JavaScript-2015

Avons-nous quelque chose dans ECMAScript-6 pour la même chose? Oui nous faisons ...

Number.isNaN(x); // true

La mise en œuvre de l’ES6 sera également utile pour les cas ci-dessus tels que

Number.isNaN(undefined); // false
Number.isNaN({}); // false    
Number.isNaN("lorem ipsum"); // false

alors que la fonction globale ECMAScript-5 isNaN s'affiche dans true pour les cas ci-dessus, qui peuvent parfois ne pas correspondre à nos attentes.

44
dopeddude