2009-05-11 13 views
267

intente ejecutar el siguiente en JavaScript:¿Cómo puedo solucionar el comportamiento octal de ParseInt de 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 integer, y puesto que no hay "8" o "9" en la base-8, la función devuelve cero. Nos guste o no, this is by design.

¿Cuáles son las soluciones?

Nota: Para completar, estoy a punto de publicar una solución, pero es una solución que odio, así que publique otras respuestas/mejores.


Actualización:

La quinta edición de la norma JavaScript (ECMA-262) introduce un cambio importante que elimina este comportamiento. Mozilla tiene un buen write-up.

+21

Paso 1) Hazte un favor y siempre incluye la raíz como se menciona en las respuestas anteriores, así como en el libro de Doug. Paso 2) Si realmente quieres aprender JavaScript, obtén una copia del libro de Doug. Es invaluable Mi libro favorito hasta ahora. Aquí hay una reseña fyi: http://realtech.burningbird.net/learning-javascript/basics/javascript-the-good-parts – fuentesjr

+8

En los navegadores compatibles con ECMAScript 5th Edition, como Internet Explorer 9, el parámetro base predeterminado es '10 '(decimal) a menos que el número a analizar esté prefijado con' 0x', por ejemplo '0xFF', en cuyo caso el parámetro base se establece por defecto en 16. Con suerte, un día, este problema será un recuerdo lejano. –

+2

¿Qué tal solo '+ '08 '=== 8'? ¡Cierto! Tal vez realmente necesites 'parseInt' para tu código real, pero no para lo anterior. – kojiro

Respuesta

316

Esta es una Gotcha JavaScript común con una solución sencilla:

Sólo specify the base, o 'raíz', así:

parseInt('08',10); // 8 

También es posible usar Number:

Number('08'); // 8 
+55

* Número *. Glorioso. – Portman

+9

El número necesita cotizaciones alrededor del 08. También tenga cuidado, Número ('08.123 ') producirá 8.123 como su resultado. Si realmente quiere un número entero, no use Number (o coincida con el patrón de su entrada para garantizar números enteros solamente). –

+3

Número (08); me da 8 en Firefox y IE. –

24

Desde parseInt documentation, use el argumento opcional radix 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 extra en cada parseo) así que espero que haya una Mejor Manera.

+6

si no le gusta Verbosity, simplemente haga su propia función que llame a la función incorporada y complete los argumentos que siempre mantente constante. –

+3

Riiiiiiight, porque no es como si todas las personas en StackOverflow lo criticaran por escribir la función parseIntB10. Escribir su propia función de envoltura es una idea terrible para este propósito. –

+2

@iftrue: Creo que no entendiste mi punto. Personalmente, no me importa hacer parseInt (someString, 10) en todas partes para asegurarme de forzar la base 10. Al OP parece no gustarle este enfoque, por lo que sugerí una alternativa, que no usaría personalmente pero tal vez se encuentre con la suya. necesariamente. (Este es aparentemente el pensamiento detrás de JQuery: hazlo conveniente agregando complejidad extra. No uso JQuery, pero mucha gente lo encuentra útil). –

10

Especificar la base:

var number = parseInt(s, 10); 
+0

Wow ustedes son rápidos. Incluso tuve mi respuesta en el portapapeles. ¿Estás conectado directamente a Internet, Neo-style? – Portman

+14

@Portman: no hay internet. – RichieHindle

+1

Por qué demonios no está predeterminado a base 10 –

11
function parseDecimal(s) { return parseInt(s, 10); } 

edición: 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 hora de la llamada parseInt(). Tiene la desventaja de ser una función no estándar: más conveniente para usted si la usa mucho, pero tal vez más confusa para otros.

+0

+1 para ponerlo en una función nombrada y, por lo tanto, hacerlo autodocumentar. – RichieHindle

7

¿Sería muy malo reemplazar parseInt con una versión que asume decimal si no tiene un segundo parámetro? (Nota - no probado)

parseIntImpl = parseInt 
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)} 
+2

sí, eso sería malo: rompería otro código que dependía del comportamiento estándar. – jes5199

+4

Eso es cierto, pero no hay mucho de eso. Tampoco es un comportamiento estándar: el soporte octal es opcional. –

+1

Pero también está dejando caer soporte hexagonal que no es opcional, ¿o sí? Esto siempre debe ser cierto: 'parseInt (" 0xFFFFFF ") === 16777215', pero con su travieso hack en su lugar ya no funciona' parseInt ("0xFFFFFF") === 0' – Timo

42

Si sabe 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 miras hacia 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 ...

+0

"Binario no". ¡Gran respuesta! Siempre hay más que aprender :) –

+2

¿Por qué dos operaciones cuando un binario o sería suficiente? –

+0

@Oleg, ¿por qué bastaría? – Sebastian

4

Si usted ha hecho un montón de codificación ya con parseInt y no quiere añadir", 10" a todo, sólo puede reemplazar 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); 
}; 

que pueden confundir a un lector más tarde, así que hacer una función parseInt10() podría ser más auto-explicativo. Personalmente prefiero usar una función simple que tener que agregar ", 10" todo el tiempo, solo crea más oportunidades para errores.

5

¿Qué tal esto para decimal:

('09'-0) === 9 // true 

('009'-0) === 9 // true 
3

Usted puede también, en lugar de utilizar parseFloat o parseInt, utilice el operador unitario +.

+"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 

MDN Link

El operador unario mas precede a su operando y evalúa a su operando pero los intentos de la convierte en un número, si ISN' t ya Aunque la negación unaria (-) también puede convertir no números, unary plus es la forma más rápida y preferida de convertir algo en un número, porque no realiza ninguna otra operación en el número.

Cuestiones relacionadas