Si tu connais les bases des tableaux JavaScript, map(), filter() et reduce() sont les trois méthodes qui vont transformer ta façon d'écrire du code. Fini les boucles for qui accumulent du code, fini les variables temporaires partout — ces trois méthodes permettent de transformer, filtrer et agréger des données en une ligne, de façon lisible et sans effets de bord. Ce guide t'explique chacune en profondeur, avec des exemples concrets tirés du vrai développement front-end.
Avant de commencer : les callbacks
Les trois méthodes fonctionnent sur le même principe : elles prennent une fonction callback en argument, qu'elles appellent pour chaque élément du tableau. Si tu n'es pas à l'aise avec les fonctions en JavaScript, relis d'abord notre article sur les closures et la portée des variables — ça posera les bases nécessaires.
const nombres = [1, 2, 3, 4, 5];
// Callback classique
nombres.forEach(function(n) {
console.log(n);
});
// Avec une arrow function (syntaxe moderne — préférable)
nombres.forEach(n => console.log(n));
Les trois méthodes qui suivent utilisent toutes la même syntaxe avec arrow function. Une fois que tu comprends l'une, les deux autres sont immédiates.
map() — Transformer chaque élément
map() crée un nouveau tableau en appliquant une fonction à chaque élément. Le tableau original reste intact. C'est la méthode de transformation par excellence.
const nombres = [1, 2, 3, 4, 5];
// ❌ Façon boucle for
const doubles = [];
for (let i = 0; i < nombres.length; i++) {
doubles.push(nombres[i] * 2);
}
// ✅ Avec map() — une ligne
const doubles = nombres.map(n => n * 2);
// [2, 4, 6, 8, 10]
// Le tableau original est intact
console.log(nombres); // [1, 2, 3, 4, 5]
Le callback de map() reçoit jusqu'à 3 arguments : l'élément, l'index, et le tableau complet.
// Exemples concrets
const prenoms = ['alice', 'bob', 'charlie'];
// Mettre en majuscules
const majuscules = prenoms.map(p => p.toUpperCase());
// ['ALICE', 'BOB', 'CHARLIE']
// Transformer des objets
const utilisateurs = [
{ nom: 'Alice', age: 25 },
{ nom: 'Bob', age: 30 },
];
const noms = utilisateurs.map(u => u.nom);
// ['Alice', 'Bob']
const profilsResume = utilisateurs.map(u => ({
nom: u.nom,
majeur: u.age >= 18
}));
// [{ nom: 'Alice', majeur: true }, { nom: 'Bob', majeur: true }]
// Utiliser l'index
const numerotes = prenoms.map((p, i) => `${i + 1}. ${p}`);
// ['1. alice', '2. bob', '3. charlie']
filter() — Garder seulement ce qui correspond
filter() crée un nouveau tableau contenant uniquement les éléments pour lesquels le callback retourne true. C'est la méthode de sélection.
const nombres = [1, 2, 3, 4, 5, 6, 7, 8];
// Garder les pairs
const pairs = nombres.filter(n => n % 2 === 0);
// [2, 4, 6, 8]
// Garder les supérieurs à 4
const grands = nombres.filter(n => n > 4);
// [5, 6, 7, 8]
// Filtrer des objets
const produits = [
{ nom: 'Laptop', prix: 1200, stock: 0 },
{ nom: 'Souris', prix: 35, stock: 50 },
{ nom: 'Clavier', prix: 89, stock: 12 },
{ nom: 'Écran', prix: 450, stock: 0 },
];
const disponibles = produits.filter(p => p.stock > 0);
// [{ nom: 'Souris', ... }, { nom: 'Clavier', ... }]
const prixAbordable = produits.filter(p => p.prix < 100 && p.stock > 0);
// [{ nom: 'Souris', ... }, { nom: 'Clavier', ... }]
// Supprimer les doublons avec filter (astuce)
const avecDoublons = [1, 2, 2, 3, 3, 3, 4];
const sansDoublons = avecDoublons.filter((val, i, arr) => arr.indexOf(val) === i);
// [1, 2, 3, 4]
reduce() — Accumuler vers un résultat unique
reduce() est la plus puissante des trois — et la plus déroutante au début. Elle réduit un tableau à une seule valeur en accumulant les éléments un par un. Cette valeur peut être un nombre, une chaîne, un objet, ou même un nouveau tableau.
// Syntaxe
array.reduce((accumulateur, elementCourant) => {
return nouvelAccumulateur;
}, valeurInitiale);
// Somme d'un tableau
const nombres = [1, 2, 3, 4, 5];
const somme = nombres.reduce((acc, n) => acc + n, 0);
// 0 + 1 = 1, 1 + 2 = 3, 3 + 3 = 6, 6 + 4 = 10, 10 + 5 = 15
console.log(somme); // 15
// Maximum d'un tableau
const max = nombres.reduce((acc, n) => n > acc ? n : acc, -Infinity);
console.log(max); // 5
// Compter les occurrences
const fruits = ['pomme', 'banane', 'pomme', 'cerise', 'banane', 'pomme'];
const comptage = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
// { pomme: 3, banane: 2, cerise: 1 }
// Aplatir un tableau de tableaux
const imbriques = [[1, 2], [3, 4], [5, 6]];
const plat = imbriques.reduce((acc, arr) => acc.concat(arr), []);
// [1, 2, 3, 4, 5, 6]
La valeur initiale (deuxième argument) est cruciale. Sans elle, reduce() prend le premier élément comme accumulateur de départ — ce qui peut provoquer des bugs subtils sur des tableaux vides.
Chaîner les trois méthodes
La vraie puissance apparaît quand tu chaînes map(), filter() et reduce() ensemble. Comme chaque méthode retourne un tableau (sauf reduce() qui retourne la valeur accumulée), tu peux les appeler en séquence.
const commandes = [
{ produit: 'Laptop', prix: 1200, quantite: 1, categorie: 'électronique' },
{ produit: 'Souris', prix: 35, quantite: 3, categorie: 'électronique' },
{ produit: 'Bureau', prix: 450, quantite: 1, categorie: 'mobilier' },
{ produit: 'Clavier', prix: 89, quantite: 2, categorie: 'électronique' },
{ produit: 'Chaise', prix: 320, quantite: 1, categorie: 'mobilier' },
];
// Total des commandes électronique seulement
const totalElectronique = commandes
.filter(c => c.categorie === 'électronique') // Garder l'électronique
.map(c => c.prix * c.quantite) // Calculer le montant
.reduce((acc, montant) => acc + montant, 0); // Sommer
console.log(totalElectronique); // 1200 + 105 + 178 = 1483
En 3 lignes, tu as filtré, transformé et agrégé — sans variable temporaire, sans mutation. Compare avec l'équivalent en boucles :
// ❌ Version boucles for — 8 lignes, une variable muable
let totalElectronique = 0;
for (let i = 0; i < commandes.length; i++) {
if (commandes[i].categorie === 'électronique') {
totalElectronique += commandes[i].prix * commandes[i].quantite;
}
}
// ✅ Version chaînée — 5 lignes, 0 mutation
const totalElectronique = commandes
.filter(c => c.categorie === 'électronique')
.map(c => c.prix * c.quantite)
.reduce((acc, montant) => acc + montant, 0);
Cas d'usage réels : dans une app React
Ces méthodes sont au cœur de tout développement React moderne. Que tu fasses de la manipulation du DOM ou du rendu de composants, tu les utiliseras constamment.
// Composant liste filtrée et transformée
function ListeProduits({ produits, categorieActive, recherche }) {
const produitsFiltres = produits
.filter(p => categorieActive === 'tous' || p.categorie === categorieActive)
.filter(p => p.nom.toLowerCase().includes(recherche.toLowerCase()))
.map(p => ({
...p,
prixFormate: new Intl.NumberFormat('fr-FR', {
style: 'currency', currency: 'EUR'
}).format(p.prix)
}));
return (
<ul>
{produitsFiltres.map(p => (
<li key={p.id}>
{p.nom} — {p.prixFormate}
</li>
))}
</ul>
);
}
Les erreurs classiques
1. Oublier le return dans map()
// ❌ Sans return avec des accolades — retourne undefined pour chaque élément
const resultat = [1, 2, 3].map(n => {
n * 2; // Pas de return !
});
console.log(resultat); // [undefined, undefined, undefined]
// ✅ Arrow function implicite (sans accolades)
const resultat = [1, 2, 3].map(n => n * 2);
// ✅ Avec accolades — return explicite obligatoire
const resultat = [1, 2, 3].map(n => {
return n * 2;
});
2. Muter le tableau dans map()
const objets = [{ val: 1 }, { val: 2 }, { val: 3 }];
// ❌ Mutation de l'objet original
const modifies = objets.map(o => {
o.val = o.val * 2; // Mute l'objet original !
return o;
});
console.log(objets[0].val); // 2 — l'original est modifié
// ✅ Créer un nouvel objet
const modifies = objets.map(o => ({ ...o, val: o.val * 2 }));
3. Oublier la valeur initiale dans reduce()
// ❌ Pas de valeur initiale — crash sur tableau vide
const vide = [];
vide.reduce((acc, n) => acc + n); // TypeError: Reduce of empty array
// ✅ Toujours fournir une valeur initiale
vide.reduce((acc, n) => acc + n, 0); // 0
4. Utiliser forEach quand on veut un résultat
// ❌ forEach ne retourne rien
const doubles = [1, 2, 3].forEach(n => n * 2); // undefined
// ✅ map() retourne un nouveau tableau
const doubles = [1, 2, 3].map(n => n * 2); // [2, 4, 6]
find() et findIndex() — bonus indispensables
Deux méthodes dans la même famille qui complètent parfaitement le trio :
const utilisateurs = [
{ id: 1, nom: 'Alice' },
{ id: 2, nom: 'Bob' },
{ id: 3, nom: 'Charlie' },
];
// find() — retourne le premier élément qui correspond
const bob = utilisateurs.find(u => u.nom === 'Bob');
// { id: 2, nom: 'Bob' }
// findIndex() — retourne l'index du premier élément qui correspond
const indexBob = utilisateurs.findIndex(u => u.nom === 'Bob');
// 1
// some() — au moins un élément correspond ?
const aUnAdmin = utilisateurs.some(u => u.role === 'admin'); // false
// every() — tous les éléments correspondent ?
const tousMajeurs = utilisateurs.every(u => u.age >= 18);
Quand utiliser quoi ?
| Méthode | Quand l'utiliser | Retourne |
|---|---|---|
map() | Transformer chaque élément | Nouveau tableau (même longueur) |
filter() | Sélectionner des éléments selon un critère | Nouveau tableau (longueur ≤) |
reduce() | Agréger en une valeur (somme, objet, etc.) | N'importe quel type |
find() | Trouver un élément spécifique | L'élément ou undefined |
forEach() | Effets de bord (log, mutation externe) | undefined |
Conclusion
map(), filter() et reduce() sont les outils qui font la différence entre du JavaScript débutant et du JavaScript professionnel. Ces méthodes permettent d'écrire du code déclaratif — tu décris ce que tu veux plutôt que comment le faire. Le résultat : moins de bugs, plus de lisibilité, et un code qui se comprend en un coup d'œil.
Les points clés :
map()— transformer, même nombre d'éléments, toujours un returnfilter()— sélectionner, moins d'éléments en sortie, callback doit retourner booleanreduce()— agréger, toujours fournir une valeur initiale, très polyvalent- Chaînage — la vraie puissance :
.filter().map().reduce() - Jamais muter l'original — toujours créer de nouvelles valeurs
Pour aller plus loin sur les subtilités du langage, notre guide sur les closures JavaScript est la prochaine étape naturelle — comprendre la portée lexicale t'aidera à maîtriser les callbacks avancés. Et pour la gestion des données asynchrones dans les tableaux, consulte notre guide sur async/await et les Promises.
La documentation de référence pour chaque méthode : MDN Array.map(), MDN Array.filter(), MDN Array.reduce().
Pour pratiquer directement dans le navigateur, retrouve nos ateliers JavaScript interactifs GoGoKodo — map, filter et reduce sont au programme des exercices sur les tableaux.