¿Por qué parseInt produce NaN con Array#map?

Resuelto brad asked hace 15 años • 8 respuestas

De la red de desarrolladores de Mozilla :

[1,4,9].map(Math.sqrt)

rendirá:

[1,2,3]

¿Por qué entonces hace esto?

['1','2','3'].map(parseInt)

producir esto:

[1, NaN, NaN]

Lo he probado en Firefox 3.0.1 y Chrome 0.3 y, como descargo de responsabilidad, sé que esta no es una funcionalidad para varios navegadores (no IE).

Descubrí que lo siguiente logrará el efecto deseado. Sin embargo, todavía no explica el comportamiento errático de parseInt.

['1','2','3'].map(function(i){return +i;}) // returns [1,2,3]
brad avatar Nov 04 '08 23:11 brad
Aceptado

La función de devolución de llamada Array.maptiene tres parámetros:

Desde la misma página de Mozilla a la que vinculó:

La devolución de llamada se invoca con tres argumentos: el valor del elemento, el índice del elemento y el objeto Array que se está atravesando".

Entonces, si llamas a una función parseIntque realmente espera dos argumentos, el segundo argumento será el índice del elemento.

En este caso, terminaste igualando parseIntcon las bases 0, 1 y 2 por turno. El primero es lo mismo que no proporcionar el parámetro, por lo que se establece de forma predeterminada según la entrada (base 10, en este caso). La base 1 es una base numérica imposible y el 3 no es un número válido en base 2:

parseInt('1', 0); // OK - gives 1
parseInt('2', 1); // FAIL - 1 isn't a legal radix
parseInt('3', 2); // FAIL - 3 isn't legal in base 2 

Entonces, en este caso, necesitas la función contenedora:

['1','2','3'].map(function(num) { return parseInt(num, 10); });

o con sintaxis ES2015+:

['1','2','3'].map(num => parseInt(num, 10));

(En ambos casos, es mejor proporcionar explícitamente una base parseIntcomo se muestra, porque de lo contrario adivina la base en función de la entrada. En algunos navegadores más antiguos, un 0 inicial hacía que adivinara octal, lo que tendía a ser problemático. Aún así adivina hexadecimal si la cadena comienza con 0x.)

Alnitak avatar Nov 04 '2008 17:11 Alnitak

mapestá pasando un segundo argumento, que (en muchos de los casos) está arruinando parseIntel parámetro de base de '.

Si estás usando un guión bajo, puedes hacer:

['10','1','100'].map(_.partial(parseInt, _, 10))

O sin guión bajo:

['10','1','100'].map(function(x) { return parseInt(x, 10); });

philfreo avatar Nov 10 '2014 23:11 philfreo

Podrías resolver este problema usando Número como función iterativa:

var a = ['0', '1', '2', '10', '15', '57'].map(Number);

console.log(a);
Expandir fragmento

Sin el nuevo operador, Número se puede utilizar para realizar la conversión de tipos. Sin embargo, difiere de parseInt: no analiza la cadena y devuelve NaN si el número no se puede convertir. Por ejemplo:

console.log(parseInt("19asdf"));
console.log(Number("19asf"));
Expandir fragmento

acontell avatar Nov 12 '2016 13:11 acontell

Apuesto a que algo extraño está sucediendo con el segundo parámetro de parseInt, la base. Por qué se rompe con el uso de Array.map y no cuando lo llamas directamente, no lo sé.

//  Works fine
parseInt( 4 );
parseInt( 9 );

//  Breaks!  Why?
[1,4,9].map( parseInt );

//  Fixes the problem
[1,4,9].map( function( num ){ return parseInt( num, 10 ) } );
Peter Bailey avatar Nov 04 '2008 16:11 Peter Bailey

Puede usar la función de flecha ES2015/ES6 y simplemente pasar el número a parseInt. El valor predeterminado para radix será 10

[10, 20, 30].map(x => parseInt(x))

O puede especificar explícitamente la base para una mejor legibilidad de su código.

[10, 20, 30].map(x => parseInt(x, 10))

En el ejemplo anterior, la base se establece explícitamente en 10

Vlad Bezden avatar Aug 17 '2016 20:08 Vlad Bezden