¿Cómo se trabaja en torno a la conducta octal parseInt de JavaScript?
-
21-08-2019 - |
Pregunta
Trate de ejecutar el siguiente 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 !!
acabo de aprender la manera dura que JavaScript cree que el cero indica una octal número entero , y ya que no hay "8"
o "9"
en base 8, la función devuelve cero. Nos guste o no, esto es por diseño .
¿Cuáles son las soluciones?
Nota:. Para mayor abundamiento, estoy a punto de publicar una solución, pero es una solución que no me gusta, así que por favor, puesto otros mejores respuestas /
Actualización:
La quinta edición de la norma JavaScript ( ECMA-262 ) introduce un cambio importante que elimina este comportamiento. Mozilla tiene una buena escritura .
Solución
Este es un Gotcha Javascript común con una solución sencilla:
especificar la base , o radix ', así:
parseInt('08',10); // 8
También es posible usar Número :
Number('08'); // 8
Otros consejos
Si saber su valor estará en el rango entero de 32 bits, entonces ~~x
va a hacer lo correcto en todos los escenarios.
~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99) === -1
Si usted mira para arriba binario no (~
), la especificación requiere una conversión "ToInt32" para el argumento que hace la conversión obvio para un Int32 y se especifica para coaccionar NaN
valores a cero.
Sí, esto es increíblemente hacker, pero es tan conveniente ...
Desde el documentación parseInt , utilice el argumento radix opcional para especificar base 10:
parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9
Esto me parece pedante, confuso y prolijo (en realidad, un argumento adicional en cada parseInt?), Así que estoy esperando que hay una mejor manera.
function parseDecimal(s) { return parseInt(s, 10); }
editar: hacer su propia función, para hacer lo que realmente quiere, es sólo una opción si no te gusta la adición de la" 10" todo el tiempo a la llamada parseInt (). Tiene la desventaja de ser una función no estándar:. Más conveniente para usted si lo usa mucho, pero tal vez más confuso para los demás
Especificar la base:
var number = parseInt(s, 10);
¿Sería muy malo para reemplazar parseInt con una versión que asume decimal si no tiene segundo parámetro? (Nota - no probado)
parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}
¿Qué tal esto para decimal:
('09'-0) === 9 // true
('009'-0) === 9 // true
También, en lugar de utilizar parseFloat o parseInt, utilice el operador unario ( + ).
+"01"
// => 1
+"02"
// => 2
+"03"
// => 3
+"04"
// => 4
+"05"
// => 5
+"06"
// => 6
+"07"
// => 7
+"08"
// => 8
+"09"
// => 9
y por una buena medida
+"09.09"
// => 9.09
El operador de suma unaria precede a su operando y evalúa a su operando, pero los intentos de convertirlo en un número, si no lo está ya. A pesar de la negación unaria (-) también se puede convertir a los no números, más unario es la manera más rápida y preferido de convertir algo en un número , ya que no lleva a cabo ninguna otra operación en el número
Si usted ha hecho un montón de codificación ya con parseInt y no quiere añadir", 10" a todo, sólo puede anular la función de hacer de base 10 el valor por defecto:
window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
if (! rad) {
return _oldParseInt(str, 10);
}
return _oldParseInt(str, rad);
};
Esto puede confundir a un lector más adelante, así que hacer una función parseInt10 () podrían ser más fáciles de entender. Personalmente prefiero utilizar una función simple de tener que añadir", 10" todo el tiempo - sólo crea más oportunidades de errores
.