Las bondades del método .map() en JavaScript
Tags: javascript, webdev, frontenddeveloper
Published: 2020-06-01 15:00:13

# **Introducción** 
No es un hecho negable que JavaScript en la actualidad es uno de los lenguajes de programación más demandados, aceptados y utilizados en la industria del software, esto se debe, según mi opinión (y la de muchos colegas) a la evolución del lenguaje y sobre todo su adaptabilidad para la resolución de problemas. 
JavaScript fue escrito en una semana por [Brendan Eich](https://es.wikipedia.org/wiki/Brendan_Eich) en 1996, ante la necesidad de tener un lenguaje interpretado en el navegador y desde ese entonces no ha parado de evolucionar incorporando desde paradigmas de programación de otros lenguajes populares, hasta ser usado en el backend de muchos proyectos. 

![logo](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/1200px-Unofficial_JavaScript_logo_2.svg.png)

## **map() en JavaScript**
El lenguaje provee al desarrollador una serie de métodos nativos que facilitan enormemente la redacción de código legible y limpio, amén de reducir las líneas de código de un proyecto.

Uno de estos métodos es el famoso `map()` que muchas personas consideran pertenece a la última especificación estable del lenguaje ([ES6](https://www.w3schools.com/js/js_es6.asp)) pero de hecho este y varios otros métodos vienen desde mucho antes, en concreto `map()` pertenece a la especificación [ES5](https://www.w3schools.com/js/js_es5.asp) publicada en 2009, ¡hace más de una década!

Ahora bien, que les parece si echamos un vistazo a lo que dice la documentación oficial acerca del método `map()`:

> *El método `map()` crea un nuevo array con los resultados de la llamada a la función indicada aplicados a cada uno de sus elementos.*
— MDN ([Mozilla Developer Network](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/map))

Bastante comprensible, ¿no es verdad?

La W3C define a `map()` de la siguiente manera: 
> *El método `map()` crea un nuevo array con los resultados de llamar a una función para cada elemento del array. El método llama a la función proporcionada una vez para cada elemento del array, en orden*
— W3C ([World Wide Web Consortium](https://www.w3schools.com/jsref/jsref_map.asp))

Los conceptos técnicos oficiales siempre están disponibles, pero no son de mucha utilidad, es mejor complementarlos con ejemplos prácticos (se aprende a programar, programando).

Imaginemos que tenemos un array unidimensional de números primos y se desea obtener el cubo de cada elemento, ¿cómo lo resolverías? 

**Solución 1:** Se podría usar una estructura iterativa convencional (como un bucle `for` o `while` para recorrer cada posición del arreglo y modificar su valor en cada iteración.)

Por ejemplo, una posible solución usando un ciclo `for` sería: 

![solucion-con-for](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/for.png)

Donde: 
:small_blue_diamond: Creamos una función que recibirá un arreglo de números primos como parámetro.
:small_blue_diamond: Declaramos un array vació donde se almacenará el resultado final.
:small_blue_diamond: Recorremos cada posición del arreglo y en cada iteración elevamos el item al cubo usando el objeto `Math.pow`.
:small_blue_diamond: Retornamos el nuevo array.
:small_blue_diamond: Llamamos a la función 

Es posible resolver el mismo problema usando un bucle `while` usando la misma lógica como se ve a continuación: 

![solucion-con-while](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/while.png)

**Solución 2:** Podríamos usar un `forEach()`:  

![solucion-con-forEach](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/forEach.png)

Donde:
:small_blue_diamond: `primosAlCubo` es un array vació donde se almacenará el resultado final.  
:small_blue_diamond: `forEach()` se aplica sobre nuestro array de números primos y recibe una función `callback` como parámetro.
:small_blue_diamond: La función `callback` a su vez, recibe otro parámetro llamado `item` que se eleva al cubo en cada ciclo.
:small_blue_diamond: Imprimimos `primosAlCubo`

**Solución 3:** ¡Usemos `map()`!
La solución más óptima para este ejemplo se aprecia en la siguiente imagen:

![solucion-con-map](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/map.png)

Donde: 
:small_blue_diamond: `map()` se aplica sobre nuestro array de números primos y recibe una función `callback` como parámetro.
:small_blue_diamond: En cada iteración elevamos `num` al cubo y retornamos los valores.

> *Nota:* `map()` no necesita de un array auxiliar y el uso del método `push` como vimos en anteriores ejemplos, basta con almacenar el resultado en una variable o constante.  

Es posible refactorizar el código anterior usando características de de ES6 como las **arrows functions** y el operador doble asterisco (`**`) de la siguiente manera:

![solucion-con-map-refactor](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/map%20refector.png)

Donde: 
:small_blue_diamond: En lugar de pasar un `callback` usamos una arrow function cuya entrada es un número del arreglo `numerosPrimos` y la salida dicho número elevado al cubo.
:small_blue_diamond: Imprimimos `primosAlCubo`.

Si comparamos un poco las soluciones anteriores contra el uso de `map()` nos percatamos que no solo es más sencillo de usar, sino también de leer y mantener. A diferencia de usar ciclos clásicos que se involucran con el `index` de cada elemento en cada iteración es preferible usar `map()` que itera el array de manera interna. 

 

> **Pro Tip**: *`map()` siempre requiere de un `return` para su correcta ejecución, caso contrario el programa no se "quejara" arrojando un error de sintaxis, sino que devolverá un array lleno de `undefined`. Saber esto puede ahorrarte tiempo de depuración.*

## **Sintaxis**
![sintaxis](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/sintaxis.png)

:small_blue_diamond: `item`: Es el elemento actual del array que se está procesando (parámetro obligatorio).
:small_blue_diamond: `index`: Es el índice del elemento actual dentro del array (parámetro opcional).
:small_blue_diamond: `arr`: El array sobre el que se llama `map` (parámetro opcional).

## **Recorrer arreglos de objetos**
`map()` es un método que puede iterar sobre cualquier arreglo, incluso sobre arreglos de objetos. 
Imaginemos que tenemos un arreglo de objetos que almacena información de los usuarios de una aplicación y deseamos obtener el nombre completo de todos los usuarios:

![arreglo-de-objetos-map](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/users%20map.png)

Con `map()` recorremos todo el arreglo de objetos y con el uso de backticks (``) concatenamos el nombre y el apellido del usuario para posteriormente mostrarlo en pantalla. 

## **Recorrer arreglos de objetos anidados**
Ahora, supongamos que tenemos un array de objetos anidados como el siguiente:

![array-de-obejetos-anidados](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/obejto%20anidado.png)

Se desea conocer a todos los usuarios con todos sus pedidos, ¿cómo podríamos resolverlo?

Ante arreglos de objetos anidados es posible usar métodos `map()` anidados, de la siguiente manera: 

![res-array-de-obejetos-anidados](https://raw.githubusercontent.com/crisdux/img-dev-to/master/map/res%20objetos%20anidados.png)


## **Conclusiones** 
Después de haber comprendido un poco mejor el funcionamiento del método `map()` considero pertinente mencionar las siguientes conclusiones:
 
:small_orange_diamond: El método `map()` se aplica a arreglos simples, arreglos de objetos y arreglos de objetos anidados.
:small_orange_diamond: Crea un nuevo arreglo a partir de una existente.
:small_orange_diamond: **Nunca** altera la cantidad de elementos del array original.
:small_orange_diamond: No altera el arreglo original (inmutabilidad del código).
:small_orange_diamond: Recibe un `callback` como parámetro o una arrow function (si usas JavaScript moderno).
:small_orange_diamond: Cada elemento del array es un argumento para el `callback` o la arrow function.
:small_orange_diamond: Para evitar problemas lógicos y ahorrarte tiempo de depuración, siempre debe contener una clausula `return`, de otro modo devolverá un vector de `undifined´s`.
:small_orange_diamond: `map()` vs `for` o `while` : al usar `map()` no es necesario preocuparse por el estado de un bucle convencional. 
:small_orange_diamond: `map()` vs `for` o `while` : los elementos del array de operan de manera directa sin acceder a ellos por su `index`. 


---

## Referencias
- https://www.w3schools.com/jsref/jsref_map.asp
- https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/map
- https://medium.com/@xadrijo/explorando-la-funci%C3%B3n-map-en-javascript-c04c42773fb6
- https://code.tutsplus.com/es/tutorials/how-to-use-map-filter-reduce-in-javascript--cms-26209
- https://www.oscarblancarteblog.com/2019/03/11/javascript-la-funcion-map/#more-2784