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.
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;
};
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.