Conceptos básicos de JS: Array#map

Array#map, o Array.prototype.map, es un método que poseen todos lo arrays en JavaScript. Este método nos sirve para mapear un array y obtener uno nuevo, lo que en palabras más normales significa que vamos a recorrer un array y transformar sus elementos en otra cosa. Veamos un ejemplo:

const numbers = [1, 2, 3];
const doubles = numbers.map(number => number * 2);
console.log(doubles); // [2,4,6]

Lo que hace Array#map entonces es llamar la función que pasamos como argumento una vez por cada elemento del array.

Nota: Ya que Array#map devuelve un nuevo array, es una mala práctica usarlo para modificar manualmente el array inicial o hacer algún otro efecto al recorrer el array, para eso es mejor usar Array#forEach.

Si queremos hacer lo mismo que Array#map tendríamos que hacer algo similar a esto:

const numbers = [1, 2, 3];
const doubles = [];

for (const number of numbers) {
  doubles.push(number * 2);
}

console.log(doubles); // [2,4,6]

Tendríamos que crear un nuevo array vacío, recorrer el primero e ir haciendo Array#push de cada valor multiplicado por dos.

Sintaxis

La sintaxis completa de la función es la siguiente

const result = initial.map(function callback(currentValue, index, array) {
  // Devuelve un nuevo elemento
}, thisArg);

Array#map recibe dos argumentos, una función callback y un valor, cualquiera, que va a ser asignado como this del callback, en caso de usar arrow functions este valor no hace nada. El callback a su vez recibe tres argumentos, la mayoría de las veces se suele usar solo el primero y algunas veces el segundo, el primero es el valor actual por el que estamos pasando en la iteración, el segundo es el índice dentro de nuestro array y el tercero es el mismo array que estamos iterando.

Por último, la función devuelve un nuevo array con los resultados de haber ejecutado callback una vez por cada elemento del array inicial.

Implementando Array#map a mano

Veamos ahora como crear nuestro propio Array#map para entender mejor su funcionamiento. Vamos a implementarlo como una función llamada map cuyo primer valor va a ser el array a mapear y después vamos a recibir el callback y el valor de this.

function map(array, callback, thisArg) {
  const result = [];
  const boundCallback = thisArg ? callback.bind(thisArg) : callback;
  for (let index = 0; index < array.length; index++) {
    result.push(boundCallback(array[index], index, array));
  }
  return result;
}

const numbers = [1, 2, 3];
const doubles = map(numbers, number => number * 2);
console.log(doubles); // [2,4,6]

¿Qué es lo que hicimos? Nuestra función recibe los tres argumentos que dijimos antes, luego crea un array vacío llamado result y una constante llamada boundCallback que en caso de que se haya definido thisArg es igual a hacer Function#bind de callback con el valor de thisArg y en caso contrario es igual a callback. Después iteramos el array inicial y hacemos result.push del valor que devuelve el callback, al cual le pasamos el valor actual del array, el índice y el array entero. Por último devolvemos el resultado.

Casos de uso

Array#map es usado un montón en JavaScript, especialmente cuando se trabaja de una forma funcional. Es usado en React.js para transformar listas de datos en elementos de React, por ejemplo:

function List({ list }) {
  return (
    <ul>
      {list.map(item => (
        <Item key={item.id} {...item} />
      ))}
    </ul>
  );
}

ReactDOM.render(<List list={[{ id: 1 }, { id: 2 }]} />, target);

Este componente List usa Array#map para transformar cada item del array list en el elemento devuelto por el componente Item pasándole toda la información de cada item al componente.


Fuera de React puede ser usado también para trabajar con listas de elementos del DOM.

const $selectList = document.querySelectorAll("select");
const values = Array.from($selectList).map($select => $select.value);

Lo que hace el ejemplo es obtener todos los <select> de una página lo que devuelve un objeto NodeList, usando Array.from lo convertimos a un array y usamos Array#map para obtener una lista (values) de los valores de cada <select>.

Palabras finales

Este método es muy útil y es usado a diario al trabajar con Arrays en JavaScript. Si no lo habías usado antes te recomiendo probar varios ejemplos de uso para familiarizarte, cuando lo hagas vas a querer usarlo siempre, especialmente en combinación de Array#filter y Array#reduce.