web-dev-qa-db-fra.com

Pourquoi isNaN ("") est-il égal à false

J'ai une petite question (j'espère!). Dans JS, pourquoi isNaN(" ") est évalué à false, mais isNaN(" x") est évalué à true?

J'effectue des opérations numériques sur un champ de saisie de texte et vérifie si le champ est null, "" ou NaN. Lorsque quelqu'un tape une poignée d'espaces sur le terrain, ma validation échoue sur les trois, et je ne comprends pas pourquoi cela dépasse la vérification isNAN.

Merci!

144
IVR Avenger

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.

140
Antonio Haley

Vous pouvez trouver cela surprenant ou peut-être pas, mais voici un code de test pour vous montrer la folie 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

donc cela signifie que

" " == 0 == false

et 

"" == 0 == false

mais 

"" != " "

S'amuser :)

75
Nick Berardi

Pour mieux le comprendre, veuillez ouvrir Ecma-Script spec pdf à la page 43 "Numéro d'application 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 aussi donner

isNaN('Infinity'); // false
16
Rafael

Essayez d'utiliser:

alert(isNaN(parseInt("   ")));

Ou

alert(isNaN(parseFloat("    ")));
15
bendewey

De MDN 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 voudrez peut-être vérifier la réponse globale suivante, qui couvre également la comparaison NaN pour l’égalité.

Comment tester si une variable JavaScript est NaN

6
dopeddude

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
5
Greg

Si vous souhaitez implémenter une fonction isNumber précise, voici une façon de procéder depuis Javascript: Les bonnes parties par Douglas Crockford

var isNumber = function isNumber(value) {
   return typeof value === 'number' && 
   isFinite(value);
}
4
Brian Grinstead

Je ne suis pas sûr pourquoi , mais pour résoudre le problème, vous pouvez toujours réduire les blancs avant de vérifier. Vous voulez probablement faire ça quand même.

2
Joel Coehoorn

La fonction isNaN("") effectue un String to Number type coercion

ECMAScript 3-5 définit les valeurs de retour suivantes pour l'opérateur typeof:

  • undefined
  • objet (null, objets, tableaux)
  • booléen
  • nombre
  • chaîne
  • une 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, elle teste plutôt la valeur contrainte. Par exemple, les booléens et les chaînes sont forcés à devenir des nombres, alors vous voudrez peut-être appeler cette fonction comme isNumberCoerced()

s'il n'est pas nécessaire de tester types autre que chaîne et nombre, l'extrait suivant peut être utilisé dans le cadre d'une condition:

if (!isNaN(s) && s.toString().trim()!='') // 's' can be boolean, number or string
    alert("s is a number")
2
Steven Pribilinskiy

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);
}
1
Bat_Programmer

Le fait que isNaN(" ") soit faux fait partie du comportement déroutant de la fonction globale isNaN en raison de la contrainte exercée sur les non-nombres par 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 nombre. La valeur résultante est ensuite testée pour déterminer si elle est NaN. Ainsi, pour les non-nombres qui, soumis à une contrainte de type numérique, aboutissent à 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 nulles), la valeur "fausse" renvoyée peut être inattendue; la chaîne vide, par exemple, est sûrement "pas un nombre".

Notez également qu'avec ECMAScript 6, il existe maintenant la méthode Number.isNaN qui, selon MDN:

En comparaison avec la fonction globale isNaN(), Number.isNaN() ne souffre pas du problème de la conversion forcée du paramètre en nombre. Cela signifie qu'il est désormais sûr de transmettre des valeurs qui seraient normalement converties en NaN, mais qui ne sont en réalité pas la même valeur que NaN. Cela signifie également que seules les valeurs du type, qui sont aussi NaN, retournent true.

Malheureusement:

Même la méthode ECMAScript 6 Number.isNaN a ses propres problèmes, comme indiqué dans l'article de blog - Correction du problème déplorable de JavaScript et ES6 NaN .

1
lucono

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 Processus DTC) peut produire un simple vrai | false tel que "", " ", " 000", ne peut pas être NaN. 

Cela signifie que le argument fourni subira d'abord un conversion comme dans:

function isNaNDemo(arg){
   var x = new Number(arg).valueOf();
   return x != x;
}

Explication:

Dans la première ligne du corps de la fonction, nous essayons (d’abord) de convertir correctement l’argument en objet numérique. Et (deuxième), en utilisant l’opérateur de points, nous supprimons immédiatement, pour notre propre confort, la la primitive valeur 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 à lui-même, par exemple: NaN == NaN >> false pour enfin le comparer (pour l'inégalité) avec lui-même.

De cette façon, la fonction return produira true uniquement lorsque et uniquement si le retour-argument fourni est une tentative infructueuse de conversion en un objet numérique, c'est-à-dire un nombre non significatif. nombre; 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 le DTC complètement afin que si l'argument n'est pas explicitement un nombre NaN, il retournera faux. Par conséquent, test contre les éléments suivants:

isNaNStatic(" x"); // will return false car c'est toujours une chaîne. 

Cependant: isNaNStatic(1/"x"); // will of course return true. comme par exemple isNaNStatic(NaN); >> true

Mais contrairement à isNaN, la isNaNStatic("NaN"); >> false car il (l’argument) est une chaîne ordinaire.

p.s.:La version statique d’isNaN peut s’avérer 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.

0
Bekim Bacaj

Qu'en est-il de 

function isNumberRegex(value) {        
    var pattern = /^[-+]?\d*\.?\d*$/i;
    var match = value.match(pattern);
    return value.length > 0 && match != null;
}
0
Alexander Schmidt

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 exécutée. (Sachez que NaN est également une valeur de type Number!)

Btw. c'est commun pour les fonctions intégrées tout - si elles attendent un argument d'un certain type, cet argument sera converti à l'aide des fonctions de conversion standard. Il existe des conversions standard entre tous les types de base (bool, chaîne, nombre, objet, date, null, non défini). 

La conversion standard de String à Number peut être appelée explicitement avec Number(). Nous pouvons donc voir que:

  • Number(" ") est évalué à 0 
  • Number(" x") est évalué à NaN

Compte tenu de 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" en nombres équivalents. La conversion ignore d’abord les espaces blancs (donc "123" est valide), puis essaie d’analyser les silences sous forme de nombre. S'il n'est pas analysable sous forme de 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 uniquement des espaces 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

0
JacquesB

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

0
kiranvj

J'ai écrit cette petite fonction rapide pour 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. :)

0
XtraSimplicity

Cette fonction semblait 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;
        }
    }
}
0
bruno negrao

Lors de la vérification si certaines valeurs de chaîne avec des espaces ou " "is isNaN peuvent essayer de valider une chaîne, exemple:

// value = "123 " if (value.match(/\s/) || isNaN(value)) { // do something }

0
Channox

NaN! == "pas un nombre"

NaN est une valeur de type type

c'est 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 voulez déterminer si la valeur est NaN, essayez d’abord de la convertir en valeur numérique.

0
saltfish

isNAN(<argument>) est une fonction permettant de savoir si un argument donné est un nombre illégal .isNaN convertit 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.

Autrement dit, isNaN (foo) est équivalent à isNaN (Number (foo)) Il accepte toutes les chaînes dont tous les chiffres sont des nombres pour des raisons évidentes. Par ex.

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
0
Om Prakash Sao