Ver Mensaje Individual
  #1 (permalink)  
Antiguo 10/05/2016, 00:00
eContento
 
Fecha de Ingreso: junio-2004
Mensajes: 621
Antigüedad: 19 años, 11 meses
Puntos: 25
De acuerdo ¿porqué ['10','10','10','10','10'].map(parseInt) da [10, NaN, 2, 3, 4]?

Hola,

El otro día un amigo me enseñó algo que vio circulando por la redes sociales y que es una de esas cosas de JavaScript que exasperan a programadores de otros lenguajes que esperan un comportamiento similar al que están acostumbrados sin profundizar en lo que hay debajo.

Y es que si abres una consola de un navegador y evalúas la siguiente expresión:
Código:
['10','10','10','10','10'].map(parseInt)
obtienes:
Código:
[10, NaN, 2, 3, 4]
Y claro, me preguntó ¿tú sabes por qué es? Al principio no me di cuenta, pero intuía porque era. Y no me quedó más remedio que hacer unas comprobaciones, para ver si estaba en lo cierto, y he querido compartir el resultado con vosotros, por si alguien quiere arrojar más luz.

La función map funciona de la siguiente manera: a cada elemento del array le aplica la función que recibe como argumento, en este caso parseInt. Pero map llama a esta función ¿sólo con el elemento que está tratando o con más datos? Esto lo comprobamos fácilmente definiendo una función que imprima por consola los parámetros que recibe:

Código:
function miFuncion(){
  console.log(arguments);
}

['a','b'].map(miFuncion)
En este caso, vemos que para cada elemento imprime:
Cita:
["a", 0, Array[2]]
["b", 1, Array[2]]
Es decir, que map llama a miFunción con una terna de valores formada por el propio valor, por la posición que ocupa en el array, y por el propio array.

De esta forma, volviendo a nuestro problema original de
Código:
['10','10','10','10','10'].map(parseInt)
en la segunda posición del array está llamando a parseInt('10',1,Array[5]);

Pero parseInt puede recibir un segundo parámetro opcional que es el radix, la base. Por ejemplo, sabemos que FF en hexadecimal es 255.

Código:
console.log(paseInt('ff',16))
255
Así que ¿cómo se pinta 'cualquier número' en base 1? NaN
Código:
console.log(paseInt('101',1))
NaN
Resumiendo, si no queremos trabajar nada más que con el valor, obviando la posición, y el resto del Array, podemos encapsular la llamada a la función en nuestra propia función:

En lugar de:
Código:
['10','10','10','10','10'].map(parseInt)
Es preferible llamar a
Código:
['10','10','10','10','10'].map(function(x){
  return parseInt(x);
})
Espero que os parezcas interesantes las reflexiones aquí compartidas.

Si alguien conoce más problemas o comportamientos parecidos a éste que lo comente pues me resultan curiosos.

Un saludo
__________________
eContento
- Mis artículos y tutoriales
- Mis jsfiddles