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 au début indique un entier octal , et puisqu'il n'y a pas de "8"
ou "9"
en base 8, la fonction renvoie zéro. Qu'on le veuille ou non, c'est par conception .
Quelles sont les solutions de contournement?
Note: Par souci d'exhaustivité, je suis sur le point de poster une solution, mais c'est une solution que je déteste, alors merci de poster d'autres/meilleures réponses.
Mise à jour:
La 5ème édition du standard JavaScript ( ECMA-262 ) introduit un changement radical qui élimine ce problème. Mozilla a un bon rédaction .
Ceci est un Javascript commun avec une solution simple:
Juste spécifiez la base , ou 'radix', comme ceci:
parseInt('08',10); // 8
Vous pouvez également utiliser Number :
Number('08'); // 8
Si vous savez votre valeur sera dans la plage des entiers 32 bits signés, alors ~~x
fera la bonne chose dans tous les scénarios.
~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99) === -1
Si vous recherchez pas binaire (~
), la spécification nécessite une conversion "ToInt32" pour l'argument qui effectue la conversion évidente en Int32 et est spécifié pour contraindre les valeurs de NaN
à zéro.
Oui, c'est incroyablement hack mais c'est tellement pratique ...
Dans la documentation de parseInt , utilisez l'argument facultatif radix pour spécifier la base 10:
parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9
Cela me semble pédant, déroutant et verbeux (en réalité, un argument supplémentaire dans chaque analyse syntaxique?), Alors j'espère qu'il existe une meilleure façon.
function parseDecimal(s) { return parseInt(s, 10); }
edit: créer votre propre fonction, faire ce que vous voulez vraiment, n’est qu’une option si vous n’aimez pas ajouter tout le temps le ", 10" à l’appel parseInt (). Cela a l’inconvénient d’être une fonction non standard: plus pratique pour vous si vous l’utilisez beaucoup, mais peut-être plus déroutant pour d’autres.
Spécifiez la base:
var number = parseInt(s, 10);
Serait-il très vilain de remplacer parseInt par une version supposée décimale si elle n’a pas de second paramètre? (note - non testé)
parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}
Vous pouvez également, au lieu d'utiliser parseFloat ou parseInt, utiliser 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 unaire plus précède son opérande et en évalue l'opérande, mais tente de le convertir en nombre, s'il ne l'est pas déjà. Bien que la négation unaire (-) puisse aussi convertir des non-nombres, unaire plus est le moyen le plus rapide et préféré de convertir quelque chose en nombre , car effectuer toute autre opération sur le numéro.
Que diriez-vous de cela pour la décimale:
('09'-0) === 9 // true
('009'-0) === 9 // true
Si vous avez déjà codé beaucoup avec parseInt et que vous ne voulez pas ajouter ", 10" à tout, vous pouvez simplement remplacer la fonction pour que la base 10 soit 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 risquerait de semer la confusion chez un lecteur ultérieur. Par conséquent, créer une fonction parseInt10 () pourrait être plus explicite. Personnellement, je préfère utiliser une fonction simple que d’ajouter ", 10" tout le temps - crée simplement plus de possibilités d’erreurs.