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!

Était-ce utile?

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("    ")));

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 fonction:

  

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 fonction isNaN est appelée avec un seul numéro d'argument, les étapes suivantes sont entreprises:

     
      
  1. Soit num ? ToNumber (number) .
  2.   
  3. Si num est NaN , retournez true .
  4.   
  5. Sinon, renvoyez false .
  6.   

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 de StringNumericLiteral , le résultat de ToNumber est NaN .

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 fonction isNaN 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 de NaN . 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 en NaN , mais ne sont en réalité pas la même valeur que NaN . Cela signifie également que seules les valeurs du numéro de type, qui sont également NaN , retournent true .

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 }

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top