Une liste d'utilisateurs à afficher, une liste de prix à convertir, une liste d'identifiants à envoyer : dans les trois cas, on part d'un tableau et on veut le même nombre d'éléments, sous une autre forme.
C'est exactement le travail de map, et c'est le seul qu'il accepte de faire.
Définition
map est une méthode d'Array (tableau) qui appelle une fonction sur chaque élément et rend un nouveau tableau composé des valeurs renvoyées. Le tableau de départ reste intact, et le tableau d'arrivée a toujours la même longueur.
const prix = [10, 25, 4];
const doubles = prix.map((p) => p * 2);
console.log(doubles); // [ 20, 50, 8 ]
console.log(prix); // [ 10, 25, 4 ], intact
const utilisateurs = [{ nom: "Ada" }, { nom: "Alan" }];
console.log(utilisateurs.map((u) => u.nom)); // [ 'Ada', 'Alan' ]Cette longueur conservée est la propriété la plus utile de map : la sortie garde les positions de l'entrée, ce qui permet de faire correspondre les deux tableaux ensuite. Array.filter(), lui, casse cette correspondance.
La signature complète
La fonction reçoit trois arguments, dont on n'utilise le plus souvent que le premier.
| Argument | Ce qu'il contient |
|---|---|
element | La valeur du tour en cours |
index | Sa position, en partant de zéro |
tableau | Le tableau parcouru, en entier |
const lettres = ["a", "b", "c"];
console.log(lettres.map((lettre, i) => `${i + 1}. ${lettre}`));
// [ '1. a', '2. b', '3. c' ]Les deux pièges classiques
Le premier consiste à oublier le return. Une accolade ouvre un corps de fonction, qui rend undefined tant que rien n'est renvoyé explicitement.
const mauvais = [1, 2].map((n) => { n * 2; });
console.log(mauvais); // [ undefined, undefined ]Le second consiste à passer une fonction toute faite sans regarder ses arguments.
console.log(["10", "10", "10"].map(parseInt)); // [ 10, NaN, 2 ]
console.log(["10", "10", "10"].map(Number)); // [ 10, 10, 10 ]map passe l'index en deuxième argument, et parseInt lit ce deuxième argument comme une base de numération. Le deuxième appel convertit donc en base 1, ce qui n'existe pas, et le troisième en base 2.
Questions fréquentes
map ou Array.forEach() ?
La question se tranche sur la valeur de retour. map construit un tableau, il faut donc en faire quelque chose. Si le but est d'agir, écrire dans un journal ou envoyer un message, forEach dit l'intention sans fabriquer un tableau que personne ne lira.
Faut-il filtrer avant ou après ?
Avant, chaque fois que c'est possible. Filtrer d'abord réduit le nombre d'éléments à transformer, alors que l'ordre inverse transforme des valeurs destinées à être jetées. Sur un tableau court la différence ne se voit pas, sur dix mille lignes elle se mesure.
Pourquoi map est-il partout dans React ?
Parce qu'afficher une liste revient à transformer un tableau de données en un tableau d'éléments, ce que map fait en une expression. Chaque élément produit y réclame en plus une propriété key stable, un point détaillé dans la formation React.