Comment transformer NaN de parseInt en 0 pour une chaîne vide?

298

Est-il possible de retourner 0 au lieu de NaNlors de l'analyse des valeurs en JavaScript?

En cas de parseIntretour de la chaîne vide NaN.

Est-il possible de faire quelque chose comme ça en JavaScript pour vérifier NaN?

var value = parseInt(tbb) == NaN ? 0 : parseInt(tbb)

Ou peut-être existe-t-il une autre fonction ou un plugin jQuery qui peut faire quelque chose de similaire?

Joper
la source
72
Pour votre information, NaN != NaN. Vous en auriez besoin isNaN(value).
pimvdb le
28
Oui, il n'y a pas deux nounous identiques;)
James P.
3
Appeler parseInt()deux fois la fonction (dans le NaNcas non réussi / normal ) n'est jamais une bonne idée. En dehors de l'inefficacité, pour les imprudents si tout ce qui est passé tbbest un appel de fonction avec des effets secondaires, c'est terrible. Je n'utiliserais aucune solution ici où je vois parseInt()deux fois.
JonBrave

Réponses:

756
var s = '';

var num = parseInt(s) || 0;

Lorsqu'il n'est pas utilisé avec des valeurs booléennes, l' ||opérateur logique OR ( ) renvoie la première expression ( parseInt(s)) si elle peut être évaluée à true, sinon il renvoie la deuxième expression (0). La valeur de retour de parseInt('')est NaN. NaN est évalué à faux, donc numfinit par être mis à 0.

Matthieu
la source
6
Cela ne fonctionnera pas si s = "4s"; (il renvoie 4 ... ce qui est incorrect ...)
markzzz
1
fonction parseInt dans js analyser tous les nombres dans la chaîne
ali youhannaei
26
@markzzz Relisez la question. OP demande: " Est-il possible de retourner 0 au lieu de NaN ". OP ne veut pas vérifier si une chaîne particulière est analysable en int. OP veut obtenir 0au lieu de NaN. Ceci est résolu parfaitement par le code de Matt.
trejder le
2
@markzzzvar nextIphone = parseInt("4S") + 1; // wow it works!
Zero Distraction
2
@Matthew, veuillez utiliser les termes "fausse" ou "véridique" . parce que NaN === false est faux! mais Boolean (NaN) === Boolean (false) est vrai. le OU logique renvoie la première expression si elle peut être évaluée à "véridique"
Pablo Recalde
52

Vous pouvez également utiliser la isNaN()fonction:

var s = ''
var num = isNaN(parseInt(s)) ? 0 : parseInt(s)
gprasant
la source
12
Pourquoi appeler parseInt(s)deux fois? En outre, cela devrait êtreparseInt(s, 10)
Dexygen
2
@GeorgeJempty Un radix de "10" est par défaut; ce paramètre est facultatif. Bon point pour appeler parseInt()deux fois cependant.
Automne Leonard
8
@AutumnLeonard, ce n'est que vrai. Si votre chaîne commence par un 0, cela suppose que le nombre est au format octal, donc parseInt ('077') vous donne 63. Cela peut conduire à de très mauvaises recherches de bogues, vous devez donc toujours spécifier le deuxième paramètre. voir par exemple stackoverflow.com/questions/8763396/…
chuck258
22

J'ai été surpris de ne voir personne mentionner l'utilisation Number(). Certes, il analysera les décimales s'il est fourni, il agira donc différemment de parseInt(), cependant il suppose déjà la base 10 et transformera "" ou même "" en 0.

Chris Werner
la source
1
Oui, très pratique pour lire depuis localStorage: Number (localStorage.getItem ('appBanner.count')) + 1
Philip Murphy
Bien que cela fonctionne pour la question telle qu'elle a été posée, elle renvoie toujours NaN pour les caractères non numériques non blancs
Kyle Delaney
9

Pour les personnes qui ne sont pas limitées à parseInt, vous pouvez utiliser l'opérateur OR au niveau du bit (qui appelle implicitement ToInt32ses opérandes).

var value = s | 0;

// NaN | 0     ==>> 0
// ''  | 0     ==>> 0
// '5' | 0     ==>> 5
// '33Ab' | 0  ==>> 0
// '0x23' | 0  ==>> 35
// 113 | 0     ==>> 113
// -12 | 0     ==>> -12
// 3.9 | 0     ==>> 3

Remarque: ToInt32est différent de parseInt. (ie parseInt('33Ab') === 33)

Ahmad Ibrahim
la source
Mais: '10000000000' | 0 === 1410065408.
trincot
@trincot yes, toute valeur> = Math.pow(2, 31)débordera.
Ahmad Ibrahim
8

Le problème

Les autres réponses ne prennent pas en compte ce qui 0est faux, et donc les suivantes seront 20 au lieu de 0:

const myNumber = parseInt('0') || 20; // 20

La solution

Je propose une fonction d'aide, qui résout la plupart des problèmes:

function getNumber({ value, defaultValue }) {
  const num = parseInt(value, 10);
  return isNaN(num) ? defaultValue : num;
}

La fonction d'assistance donnera les résultats suivants:

getNumber({ value: "0", defaultValue: 20 }); // 0
getNumber({ value: "2", defaultValue: 20 }); // 2
getNumber({ value: "2.2", defaultValue: 20 }); // 2
getNumber({ value: "any string", defaultValue: 20 }); // 20
getNumber({ value: undefined, defaultValue: 20 }); // 20
getNumber({ value: null, defaultValue: 20 }); // 20
getNumber({ value: NaN, defaultValue: 20 }); // 20
getNumber({ value: false, defaultValue: 20 }); // 20
getNumber({ value: true, defaultValue: 20 }); // 20
sqren
la source
2
Veuillez envoyer un radix à parseInt:, parseInt(string, radix)considérez ceci: pourrait parseInt("0x10") === 16également parseInt("010")produire 8dans certains navigateurs
andlrc
2
Si vous dépendez déjà de lodash pour d'autres choses, il existe une defaultTofonction pratique qui fait exactement cela: _.defaultTo(NaN, -1)retourne -1, mais _.defaultTo(0, -1);revient 0.
waldyrious
C'est un excellent point! Vous ne pouvez compter que sur le || à la fin pour fournir la valeur par défaut correcte lorsque votre valeur par défaut préférée est ZERO (accordé, c'est ce que l'OP voulait). Comme vous l'avez mentionné, en raison de la nature fausse de l'entrée '0', elle est traitée comme une entrée non valide dans ce cas, et l'instruction renverra la valeur par défaut à la place (peut-être pas ce qui était attendu!)
JonathanDavidArndt
Vous devriez sûrement utiliser un const au lieu d'appeler parseIntdeux fois
Kyle Delaney
4

Est-ce que le travail est beaucoup plus propre que l'analyse à mon avis, utilisez l'opérateur +

var s = '';
console.log(+s);

var s = '1024'
+s
1024

s = 0
+s
0

s = -1
+s
-1

s = 2.456
+s
2.456

s = ''
+s
0

s = 'wtf'
+s
NaN
PirateApp
la source
1
Très compact. Quel dommage que vous n'ayez pas obtenu plus de points. Je t'ai voté. S'il vous plaît, échangez-moi pour essayer d'attraper mon -2 acquis aujourd'hui par un troll muet ... (voir ma réponse à la fin de cette page). Je vous remercie.
Fabien Haddadi
2
var value = isNaN(parseInt(tbb)) ? 0 : parseInt(tbb);
Milap Jethwa
la source
1

Effectuez une vérification distincte pour une chaîne vide (car il s'agit d'un cas spécifique) et définissez-la sur zéro dans ce cas.

Vous pouvez appeand "0" au début, mais vous devez ensuite ajouter un préfixe pour indiquer qu'il s'agit d'un nombre décimal et non octal

Chat Schroedingers
la source
vous pensez donc qu'il vaut mieux ajouter 0 si vide?
Joper
1
Non - c'est une approche que j'ai utilisée. Dans ce cas, un contrôle séparé serait préférable. Cependant, si la solution Matts fonctionne, c'est encore plus propre.
Schroedingers Cat
1

Pourquoi ne pas remplacer la fonction? Dans ce cas, vous pouvez toujours être sûr qu'il revient 0en cas de NaN:

(function(original) {
    parseInt = function() {
        return original.apply(window, arguments) || 0;
    };
})(parseInt);

Maintenant, n'importe où dans votre code:

parseInt('') === 0
pimvdb
la source
15
Remplacer la fonction comme celle-ci pourrait confondre les programmeurs JavaScript experts qui pourraient voir cela comme un bogue. Votre fonction remplacée est susceptible d'être enterrée quelque part où elle n'est pas susceptible d'être vue. C'est créatif, mais je ne suis pas sûr de le recommander personnellement étant donné la facilité avec laquelle il suffit d'ajouter un || 0comme dans la réponse de Matt. Je vois des objets prioritaires que vous ne possédez pas en dernier recours ou, dans le cas contraire, cela coûterait beaucoup plus cher en termes de temps et de complexité.
jmort253
2
Je suis d'accord avec @ jmort253 ... C'est dangereux car la fonction est trop intelligente. Il vaut mieux faire exactement la même fonction mais avec un nom comme getSafeNumberValue ou quelque chose comme ça.
Samuel
1

J'ai eu un problème similaire (firefox v34) avec des chaînes simples comme:

var myInt = parseInt("b4");

J'ai donc trouvé un hack rapide de:

var intVal = ("" + val).replace(/[^0-9]/gi, "");

Et puis tout est devenu stupide et compliqué de gérer les flotteurs + les pouces pour des choses non simples:

var myval = "12.34";

function slowParseNumber(val, asInt){
    var ret = Number( ("" + val).replace(/[^0-9\.]/gi, "") );
    return asInt ? Math.floor(ret) : ret;
}
var floatVal = slowParseNumber(myval);

var intVal = slowParseNumber(myval, true);
console.log(floatVal, intVal);

Il renverra 0 pour des choses comme:

var intVal = slowParseNumber("b"); // yeilds 0
bob
la source
1
//////////////////////////////////////////////////////
function ToInt(x){x=parseInt(x);return isNaN(x)?0:x;}
//////////////////////////////////////////////////////
var x = ToInt('');   //->  x=0
    x = ToInt('abc') //->  x=0
    x = ToInt('0.1') //->  x=0
    x = ToInt('5.9') //->  x=5
    x = ToInt(5.9)   //->  x=5
    x = ToInt(5)     //->  x=5
AbdulRahman AlShamiri
la source
Pouvez-vous expliquer cette solution?
RamenChef
si vous voulez convertir n'importe quel nombre (comme '123 'ou 123) en entier, si vous utiliserez parseInt (' abc '),
AbdulRahman AlShamiri
si vous utilisez parseInt ('abc'), vous obtiendrez NaN mais cette fonction convertira le NaN en 0
AbdulRahman AlShamiri
Le bingo, comme alternative explicite à l' ||approche. Je sais que c'est une vieille question et réponse, mais cette réponse évite d'appeler parseInt deux fois et utilise correctement isNaN. Il a juste besoin que la radix parseInt(x, 10)soit approfondie. (Ma préférence est une variable interne distincte au lieu de réutiliser x.)
goodeye
1

J'ai créé un prototype 2 pour gérer cela pour moi, un pour un nombre et un pour une chaîne.

// This is a safety check to make sure the prototype is not already defined.
Function.prototype.method = function (name, func) {
    if (!this.prototype[name]) {
        this.prototype[name] = func;
        return this;
    }
};

// returns the int value or -1 by default if it fails
Number.method('tryParseInt', function (defaultValue) {
    return parseInt(this) == this ? parseInt(this) : (defaultValue === undefined ? -1 : defaultValue);
});

// returns the int value or -1 by default if it fails
String.method('tryParseInt', function (defaultValue) {
    return parseInt(this) == this ? parseInt(this) : (defaultValue === undefined ? -1 : defaultValue);
});

Si vous ne souhaitez pas utiliser le contrôle de sécurité, utilisez

String.prototype.tryParseInt = function(){
    /*Method body here*/
};
Number.prototype.tryParseInt = function(){
     /*Method body here*/
};

Exemple d'utilisation:

var test = 1;
console.log(test.tryParseInt()); // returns 1

var test2 = '1';
console.log(test2.tryParseInt()); // returns 1

var test3 = '1a';
console.log(test3.tryParseInt()); // returns -1 as that is the default

var test4 = '1a';
console.log(test4.tryParseInt(0));// returns 0, the specified default value
Mike
la source
1
// implicit cast
var value = parseInt(tbb*1); // see original question

Explication, pour ceux qui ne trouvent pas cela trivial:

La multiplication par un, une méthode appelée «distribution implicite», tente de transformer l'opérande de type inconnu en «nombre» de type primitif. En particulier, une chaîne vide deviendrait numéro 0, ce qui en ferait un type éligible pour parseInt () ...

Un très bon exemple a également été donné ci-dessus par PirateApp, qui a suggéré d'ajouter le signe +, forçant JavaScript à utiliser la distribution implicite de Number.

Fabien Haddadi
la source
C'est une réponse directe à la question d'origine, mon cher.
Fabien Haddadi
Cela ne fonctionnera pas pourparseInt('str'*1)
Rodion Baskakov
Pourquoi faire appel parseIntà quelque chose qui est déjà un numéro? Cela entraînera une nouvelle conversion en chaîne uniquement pour la convertir à nouveau en nombre.
trincot
0

De cette façon, pourquoi ne pas écrire une fonction et l'appeler là où vous en avez besoin. Je suppose que c'est l'entrée dans les champs du formulaire pour effectuer des calculs.

var Nanprocessor = function (entry) {
    if(entry=="NaN") {
        return 0;
    } else {
        return entry;
    }
}

 outputfield.value = Nanprocessor(x); 

// where x is a value that is collected from a from field
// i.e say x =parseInt(formfield1.value); 

qu'est-ce qui ne va pas?

Naresh
la source
Salut, wat nous empêche de suivre la méthode ci-dessus. Voudrais savoir n apprendre.
Naresh
3
Vous devez utiliser isNaN pour tester NaN.
Matthew
2
Merci Matt :) Je ne sais pas qu'il existe une fonction appelée isNaN () dans javascrip! Merci de me le faire savoir...!
Naresh
0

Voici une méthode tryParseInt que j'utilise, elle prend la valeur par défaut comme deuxième paramètre afin qu'elle puisse être tout ce dont vous avez besoin.

function tryParseInt(str, defaultValue) {
    return parseInt(str) == str ? parseInt(str) : defaultValue;
}

tryParseInt("", 0);//0 
tryParseInt("string", 0);//0 
tryParseInt("558", 0);//558
Darrelk
la source
0

une fonction d'aide qui permet toujours d'utiliser le radix

function parseIntWithFallback(s, fallback, radix) {
    var parsed = parseInt(s, radix);
    return isNaN(parsed) ? fallback : parsed;
}
Jerome Diaz
la source
0

Vous pouvez avoir du code très propre, j'ai eu des problèmes similaires et je l'ai résolu en utilisant:

var a="bcd";
~~parseInt(a);
Bishal Gautam
la source
0

Pour les autres personnes à la recherche de cette solution, utilisez simplement: ~~ sans parseInt, c'est le mode le plus propre.

var a = 'hello';
var b = ~~a;

Si NaN, il renverra 0 à la place.

OBS. Cette solution s'applique uniquement aux entiers

Marcos Mendes
la source