Comment puis-je contourner le comportement octal parseInt de JavaScript?
-
21-08-2019 - |
Question
Essayez d'exécuter ce qui suit en JavaScript:
parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!
parseInt('09'); //equals 0 !!
Je viens d'apprendre la dure que JavaScript pense que le zéro indique un octal entier et puisqu'il n'y a pas "8"
ou "9"
en base 8, la fonction retourne zéro. Qu'on le veuille ou non, c'est par la conception .
Quelles sont les solutions de contournement?
Remarque:. Pour être complet, je suis sur le point de poster une solution, mais il est une solution que je déteste, alors s'il vous plaît afficher d'autres / meilleures réponses
Mise à jour:
La 5ème édition de la norme JavaScript ( ECMA-262 ) introduit un changement de rupture qui élimine ce comportement. Mozilla a un bon écriture .
La solution
Ceci est un Gotcha Javascript commun avec une solution simple:
Il suffit de spécifier la de base, ou 'radix', comme suit:
parseInt('08',10); // 8
Vous pouvez également utiliser Numéro :
Number('08'); // 8
Autres conseils
Si vous savoir votre valeur sera dans la gamme entier signé 32 bits, puis fera la ~~x
chose correcte dans tous les scénarios.
~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99) === -1
Si vous regardez binaire non (~
), la spécification exige une conversion « ToInt32 » pour l'argument qui fait la conversion évidente à un Int32 et est spécifié pour forcer les valeurs à zéro NaN
.
Oui, cela est incroyablement hackish mais est si commode ...
De la documentation parseInt , utilisez l'argument radix optionnel pour spécifier base 10:
parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9
Cela me semble pédant, confus et bavard (vraiment, un argument supplémentaire dans chaque parseInt?) Donc j'espère qu'il ya une meilleure façon.
function parseDecimal(s) { return parseInt(s, 10); }
edit: faire votre propre fonction, faire ce que vous voulez vraiment, est juste une option si vous ne souhaitez pas ajouter le » 10" tout le temps à l'appel parseInt (). Il a l'inconvénient d'être une fonction non standard. Plus pratique pour vous si vous utilisez beaucoup, mais peut-être plus déroutant pour les autres
Spécifie la base:
var number = parseInt(s, 10);
Serait-il très méchant pour remplacer parseInt avec une version qui suppose décimale si elle n'a pas de second paramètre? (Note - n'a pas été testé)
parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}
Que diriez-vous cela pour décimales:
('09'-0) === 9 // true
('009'-0) === 9 // true
Vous pouvez également, au lieu d'utiliser parseFloat ou parseInt, utilisez l'opérateur unaire ( + ).
+"01"
// => 1
+"02"
// => 2
+"03"
// => 3
+"04"
// => 4
+"05"
// => 5
+"06"
// => 6
+"07"
// => 7
+"08"
// => 8
+"09"
// => 9
et pour faire bonne mesure
+"09.09"
// => 9.09
L'opérateur plus unaire précède son opérande et évalue son opérande mais tente de le convertir en un certain nombre, si elle est pas déjà. Bien que la négation unaire (-) peut également convertir les non-nombres, plus unaire est le moyen le plus rapide et préféré de convertir quelque chose en un certain nombre , car il ne fonctionne pas d'autres opérations sur le nombre
Si vous avez fait un tas de codage déjà avec parseInt et ne veulent pas ajouter », 10" à tout, vous pouvez simplement remplacer la fonction pour base 10 la valeur par défaut:
window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
if (! rad) {
return _oldParseInt(str, 10);
}
return _oldParseInt(str, rad);
};
Cela peut confondre un lecteur plus tard, rendant ainsi une fonction parseInt10 () pourrait être plus explicite. Personnellement, je préfère utiliser une fonction simple que d'avoir à ajouter », 10" tout le temps - juste crée plus de possibilités pour les erreurs
.