Pourquoi isNaN («») est-il égal à faux
-
05-07-2019 - |
Question
J'ai une petite question (j'espère!). Dans JS, pourquoi isNaN (")
a-t-il la valeur false, mais isNaN (" x ")
a la valeur true?
J'effectue des opérations numériques sur un champ de saisie de texte et je vérifie si ce champ est vide, "ou", ou NaN. Lorsque quelqu'un tape une poignée d'espaces dans le champ, ma validation échoue sur les trois, et je ne comprends pas pourquoi elle dépasse la vérification isNAN.
Merci!
La solution
JavaScript interprète une chaîne vide comme un 0, ce qui échoue ensuite avec le test isNAN. Vous pouvez utiliser parseInt sur la chaîne en premier, ce qui ne convertira pas la chaîne vide en 0. Le résultat devrait alors échouer, isNAN.
Autres conseils
Vous pouvez trouver cela surprenant ou peut-être pas, mais voici un code de test pour vous montrer le wackyness du moteur JavaScript.
document.write(isNaN("")) // false
document.write(isNaN(" ")) // false
document.write(isNaN(0)) // false
document.write(isNaN(null)) // false
document.write(isNaN(false)) // false
document.write("" == false) // true
document.write("" == 0) // true
document.write(" " == 0) // true
document.write(" " == false) // true
document.write(0 == false) // true
document.write(" " == "") // false
cela signifie donc que
" " == 0 == false
et
"" == 0 == false
mais
"" != " "
Amusez-vous :))
Pour mieux comprendre, ouvrez Ecma-Script spec pdf à la page 43 "Au numéro appliqué au type de chaîne"
Si une chaîne a une syntaxe numérique pouvant contenir un nombre illimité de caractères d'espacement, elle peut être convertie en type Number. La chaîne vide est évaluée à 0. La chaîne 'Infinity' devrait également donner
isNaN('Infinity'); // false
Essayez d’utiliser:
alert(isNaN(parseInt(" ")));
Ou
alert(isNaN(parseFloat(" ")));
De MDN
une> raison du problème auquel vous êtes confronté
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.
Vous pouvez vérifier la réponse globale suivante, qui couvre également la comparaison NaN pour l’égalité.
Je pense que c'est à cause de la frappe de Javascript: ''
est converti à zéro, alors que 'x'
n'est pas:
alert(' ' * 1); // 0
alert('x' * 1); // NaN
Si vous souhaitez implémenter une fonction isNumber précise, voici une façon de le faire à partir de Javascript: Les bonnes parties de Douglas Crockford [page 105]
var isNumber = function isNumber(value) {
return typeof value === 'number' &&
isFinite(value);
}
La réponse pas tout à fait correcte
La réponse hautement votée et acceptée d'Antonio Haley laisse supposer ici que ce processus passe par le code parseInt
Vous pouvez utiliser parseInt sur la chaîne ... Le résultat devrait alors échouer, isNAN.
Nous pouvons facilement réfuter cette affirmation avec la chaîne " 123abc "
:
parseInt("123abc") // 123 (a number...
isNaN("123abc") // true ...which is not a number)
Grâce à cela, nous pouvons voir que la fonction parseInt
de JavaScript renvoie "123abc" /
comme numéro
123
, mais que son estNaN La fonction
nous indique que "123abc"
n'est pas un nombre.
La réponse correcte
ECMAScript-262 définit le fonctionnement de la vérification isNaN
dans section 18.2.3 .
18.2.3
isNaN
(Nombre)La fonction
isNaN
est l'objet intrinsèque% isNaN%
. Lorsque la fonctionisNaN
est appelée avec un seul numéro d'argument, les étapes suivantes sont entreprises:
- Soit
num
?ToNumber (number)
.- Si
num
estNaN
, retourneztrue
.- Sinon, renvoyez
false
.
La fonction ToNumber
à laquelle elle fait référence est également définie dans ECMAScript- La section 7.1.3 de 262 . Ici, nous apprenons comment JavaScript traite les chaînes qui sont transmises à cette fonction.
Le premier exemple donné dans la question est une chaîne ne contenant que des caractères d'espacement. Cette section indique que:
Un
StringNumericLiteral
vide ou contenant uniquement des espaces est converti en+0
.
Le " La chaîne d'exemple "
" est donc convertie en +0
, qui est un nombre.
La même section indique également:
Si la grammaire ne peut pas interpréter la
String
comme une extension deStringNumericLiteral
, le résultat deToNumber
estNaN
.
Sans citer toutes les vérifications contenues dans cette section, le " L'exemple x "
" donné dans la question correspond à la condition ci-dessus, car il ne peut pas être interprété comme un StringNumericLiteral
. " x "
est donc converti en NaN
.
Je ne suis pas certain pourquoi , mais pour résoudre le problème, vous pouvez toujours supprimer les espaces avant de vérifier. Vous voulez probablement le faire quand même.
La fonction isNaN ("")
effectue une chaîne en chiffre contrainte de type
ECMAScript 3-5 définit les valeurs de retour suivantes pour le typeof opérateur:
- non défini
- objet (null, objets, tableaux)
- booléen
- numéro
- chaîne
- fonction
Mieux vaut envelopper notre test dans un corps de fonction:
function isNumber (s) {
return typeof s == 'number'? true
: typeof s == 'string'? (s.trim() === ''? false : !isNaN(s))
: (typeof s).match(/object|function/)? false
: !isNaN(s)
}
Cette fonction n'est pas destinée à tester la variable type , mais à tester la valeur contrainte . Par exemple, les booléens et les chaînes sont forcés à devenir des nombres. Vous pouvez peut-être appeler cette fonction comme isNumberCoerced ()
s'il n'est pas nécessaire de tester les types autres que chaîne et numéro , l'extrait de code suivant peut être utilisé dans le cadre de certaines conditions. :
if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
alert("s is a number")
Je vous suggère d'utiliser la fonction suivante si vous voulez vraiment vérifier si c'est un entier:
function isInteger(s)
{
return Math.ceil(s) == Math.floor(s);
}
Que isNaN ("")
soit faux fait partie du comportement déroutant de la fonction globale isNaN
en raison de sa contrainte de non-nombres à un type numérique .
De MDN :
Depuis les toutes premières versions de la spécification de la fonction
isNaN
, son comportement pour les arguments non numériques a été source de confusion. Lorsque l'argument de la fonctionisNaN
n'est pas de type Number, la valeur est d'abord contrainte à un Number. La valeur résultante est ensuite testée pour déterminer s'il s'agit deNaN
. Ainsi, pour les non-nombres qui, lorsqu'ils sont forcés au type numérique, résultent en une valeur numérique non-NaN valide (notamment les primitives chaîne vide et booléenne, qui, lorsqu'elles sont forcées, donnent des valeurs numériques nulles ou égales à un), le "faux" la valeur renvoyée peut être inattendue; la chaîne vide, par exemple, n'est sûrement pas un nombre.
Notez également qu'avec ECMAScript 6, il existe également la méthode Number.isNaN
, qui selon MDN:
Par rapport à la fonction globale
isNaN ()
,Number.isNaN ()
ne pose pas le problème de la conversion forcée du paramètre en un nombre. Cela signifie qu'il est désormais sûr de transmettre des valeurs qui seraient normalement converties enNaN
, mais ne sont en réalité pas la même valeur queNaN
. Cela signifie également que seules les valeurs du numéro de type, qui sont égalementNaN
, retournenttrue
.
Malheureusement :
Même la méthode Number.isNaN
ECMAScript 6 a ses propres problèmes, comme indiqué dans l'article du blog - Résolution du problème JavaScript et du problème ES6 NaN .
Comme expliqué par d'autres, la fonction isNaN
contraindra la chaîne vide en un nombre avant de la valider, ce qui changera une chaîne vide en 0 (ce qui est un nombre valide).
Cependant, j'ai constaté que la fonction parseInt
renverrait NaN
lors d'une tentative d'analyse d'une chaîne vide ou d'une chaîne ne contenant que des espaces. En tant que telle, la combinaison suivante semble bien fonctionner:
if (isNaN (chaîne) || isNaN (parseInt (chaîne))) console.log ('Pas un nombre!');
Cette vérification fonctionnera pour les nombres positifs, les nombres négatifs et les nombres avec une virgule décimale. Je crois donc qu'elle couvre tous les cas numériques courants.
Cette fonction a semblé fonctionner dans mes tests
function isNumber(s) {
if (s === "" || s === null) {
return false;
} else {
var number = parseInt(s);
if (number == 'NaN') {
return false;
} else {
return true;
}
}
}
Qu'en est-il de
function isNumberRegex(value) {
var pattern = /^[-+]?\d*\.?\d*$/i;
var match = value.match(pattern);
return value.length > 0 && match != null;
}
La fonction isNaN
attend un nombre comme argument. Par conséquent, les arguments de tout autre type (dans votre cas, une chaîne) seront convertis en nombre avant la logique de la fonction réelle. est effectuée. (Notez que NaN
est également une valeur de type Number!)
Btw. c'est commun pour toutes les fonctions intégrées - s'ils s'attendent à un argument d'un certain type, l'argument actuel sera converti à l'aide des fonctions de conversion standard. Il existe des conversions standard entre tous les types de base (bool, chaîne, numéro, objet, date, null, non défini.)
La conversion standard de Chaîne
en Nombre
peut être appelée explicitement avec Nombre ()
. Nous pouvons donc voir que:
-
Nombre (")
correspond à0
-
Nombre ("x")
correspond àNaN
Étant donné cela, le résultat de la fonction isNaN
est tout à fait logique!
La vraie question est de savoir pourquoi la conversion standard de chaîne en nombre fonctionne comme elle le fait. La conversion chaîne à nombre est réellement destinée à convertir des chaînes numériques telles que "123". ou "17,5e4" aux nombres équivalents. La conversion ignore d’abord les espaces blancs ("123" est donc valide), puis essaie d’analyser les silences sous forme de nombre. S'il n'est pas assimilable à un nombre ("x" ne l'est pas), le résultat est NaN. Mais il existe une règle spéciale explicite selon laquelle une chaîne vide ou un espace seulement est convertie en 0. Cela explique donc la conversion.
Référence: http: //www.ecma-international .org / ecma-262 / 5.1 / # sec-9.3.1
J'ai écrit cette petite fonction rapide pour vous aider à résoudre ce problème.
function isNumber(val) {
return (val != undefined && val != null && val.toString().length > 0 && val.toString().match(/[^0-9\.\-]/g) == null);
};
Il recherche simplement les caractères non numériques (0 à 9), qui ne sont ni '-' ni '.', ni indéfinis, nuls ou vides et renvoie true s'il n'y a pas de correspondance. :)
La fonction JavaScript intégrée isNaN est, comme il fallait s'y attendre par défaut, un "opérateur de type dynamique".
Par conséquent, toutes les valeurs qui (au cours du processus DTC) peuvent donner un résultat vrai | faux tel que "" ;," " ;, " 000 "
, ne peut pas être NaN.
Cela signifie que l'argument fourni subira d'abord une conversion comme dans:
.function isNaNDemo(arg){
var x = new Number(arg).valueOf();
return x != x;
}
Explication:
Dans la ligne supérieure du corps de la fonction, nous essayons (en premier) de convertir correctement l'argument en objet numérique. Et (deuxièmement), en utilisant l’opérateur point, nous supprimons immédiatement, pour notre propre confort, la valeur de la primitive de l’objet créé.
Dans la deuxième ligne, nous prenons la valeur obtenue à l'étape précédente, et l'avantage du fait que NaN n'est égal à rien dans l'univers, pas même pour lui-même, par exemple: NaN == NaN > > false
pour enfin le comparer (pour l'inégalité) avec lui-même.
De cette manière, la fonction return produira true seulement si et seulement si le retour argument argumenté est une tentative de conversion infructueuse en objet numérique, c'est-à-dire , un nombre non numérique; par exemple, NaN.
isNaNstatic ()
Cependant, pour un opérateur de type statique, si nécessaire et si nécessaire, nous pouvons écrire une fonction beaucoup plus simple, telle que:
function isNaNstatic(x){
return x != x;
}
Et évitez complètement le code d'anomalie afin que, si l'argument n'est pas explicitement un nombre NaN, il retournera faux. C’est pourquoi nous avons testé les éléments suivants:
estNaNStatic ("x"); // retournera false
car il s'agit toujours d'une chaîne.
Cependant:
estNaNStatic (1 / "x"); // retournera bien sûr true.
comme par exemple isNaNStatic (NaN); > > vrai
.
Mais contrairement à isNaN
, le estNaNStatic ("NaN"); > > false
car il (l'argument) est une chaîne ordinaire.
p.s .: La version statique d’isNaN peut être très utile dans les scénarios de codage modernes. Et c’est peut-être une des raisons principales pour lesquelles j’ai pris le temps de publier ceci.
Cordialement.
isNAN (< argument >)
est une fonction qui indique si un argument donné est un nombre illégal.
isNaN
dactylographie les arguments en type Number. Si vous voulez vérifier si l'argument est numérique ou non? Veuillez utiliser la fonction $. IsNumeric ()
dans jQuery.
C'est-à-dire qu'isNaN (foo) est équivalent à isNaN (Number (foo)) Il accepte toutes les chaînes dont tous les chiffres sont des chiffres pour des raisons évidentes. Par exemple.
isNaN(123) //false
isNaN(-1.23) //false
isNaN(5-2) //false
isNaN(0) //false
isNaN('123') //false
isNaN('Hello') //true
isNaN('2005/12/12') //true
isNaN('') //false
isNaN(true) //false
isNaN(undefined) //true
isNaN('NaN') //true
isNaN(NaN) //true
isNaN(0 / 0) //true
je l'utilise
function isNotANumeric(val) {
if(val.trim && val.trim() == "") {
return true;
} else {
return isNaN(parseFloat(val * 1));
}
}
alert(isNotANumeric("100")); // false
alert(isNotANumeric("1a")); // true
alert(isNotANumeric("")); // true
alert(isNotANumeric(" ")); // true
NaN
! == "Ce n'est pas un nombre"
NaN
est une valeur de type de numéro
il s'agit d'une définition de isNaN () dans ECMAScript
1. Let num be ToNumber(number).
2. ReturnIfAbrupt(num).
3. If num is NaN, return true.
4. Otherwise, return false.
Essayez de convertir n'importe quelle valeur en nombre.
Number(" ") // 0
Number("x") // NaN
Number(null) // 0
Si vous souhaitez déterminer si la valeur est NaN
, vous devez d'abord essayer de la convertir en valeur numérique.
Lors de la vérification de certaines valeurs de chaîne avec des espaces ou " "
est isNaN
peut-être essayer de valider une chaîne, exemple:
// value = " 123 "
if (valeur.match (/ \ s /) || isNaN (valeur)) {
// faire quelque chose
}