Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. JavaScript
  3. Référence
  4. Objets natifs standards
  5. Array
  6. reduce()

Cette page a été traduite à partir de l'anglais par la communauté.Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.

View in EnglishAlways switch to English

Array : méthode reduce()

Baseline Widely available

Cette fonctionnalité est bien établie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis ⁨juillet 2015⁩.

La méthodereduce() des instancesArray exécute une fonction de rappel « de réduction » fournie par l'utilisateur·ice sur chaque élément du tableau, dans l'ordre, en transmettant la valeur retournée par le calcul précédent. Le résultat final de l'exécution du réducteur sur tous les éléments du tableau est une seule valeur.

La première fois que la fonction de rappel est exécutée, il n'y a pas de « valeur retournée par le calcul précédent ». Si elle est fournie, une valeur initiale peut être utilisée à la place. Sinon, l'élément du tableau d'index 0 est utilisé comme valeur initiale et l'itération commence à l'élément suivant (index 1 au lieu de l'index 0).

Exemple interactif

const array1 = [1, 2, 3, 4];// 0 + 1 + 2 + 3 + 4const initialValue = 0;const sumWithInitial = array1.reduce(  (accumulator, currentValue) => accumulator + currentValue,  initialValue,);console.log(sumWithInitial);// Résultat attendu : 10

Syntaxe

js
reduce(callbackFn)reduce(callbackFn, initialValue)

Paramètres

callbackFn

La fonction de rappel à exécuter pour chaque élément du tableau. Sa valeur de retour devient la valeur du paramètreaccumulator lors de l'appel suivant decallbackFn. Pour le dernier appel, la valeur de retour devient la valeur retournée parreduce(). La fonction est appelée avec les arguments suivants :

accumulator

La valeur résultant de l'appel précédent decallbackFn. Lors du premier appel, sa valeur estinitialValue si ce dernier est défini ; sinon, sa valeur estarray[0].

currentValue

La valeur de l'élément courant. Lors du premier appel, sa valeur estarray[0] siinitialValue est défini ; sinon, sa valeur estarray[1].

currentIndex

L'index decurrentValue dans le tableau. Lors du premier appel, sa valeur est0 siinitialValue est défini ; sinon1.

array

Le tableau sur lequelreduce() a été appelé.

initialValueFacultatif

La valeur à laquelleaccumulator est initialisé lors du premier appel de la fonction de rappel.SiinitialValue est défini,callbackFn commence à s'exécuter avec la première valeur du tableau commecurrentValue.SiinitialValue n'est pas défini,accumulator est initialisé à la première valeur du tableau, etcallbackFn commence à s'exécuter avec la seconde valeur du tableau commecurrentValue. Dans ce cas, si le tableau est vide (et qu'il n'y a donc pas de première valeur à retourner commeaccumulator), une erreur est levée.

Valeur de retour

La valeur qui résulte de l'exécution de la fonction de rappel « de réduction » sur l'ensemble du tableau jusqu'à la fin.

Exceptions

TypeError

Levée si le tableau ne contient aucun élément et que la valeur initiale n'est pas définie.

Description

La méthodereduce() est uneméthode itérative. Elle exécute une fonction de rappel « de réduction » sur tous les éléments du tableau, dans l'ordre croissant des indices, et les accumule en une seule valeur. À chaque itération, la valeur retournée parcallbackFn est transmise à nouveau àcallbackFn lors de l'appel suivant en tant qu'accumulator. La dernière valeur deaccumulator (c'est-à-dire la valeur retournée parcallbackFn lors de la dernière itération du tableau) devient la valeur retournée parreduce(). Consultez la sectionméthodes itératives pour plus d'informations sur le fonctionnement général de ces méthodes.

callbackFn n'est appelée que pour les indices du tableau qui ont des valeurs attribuées. Elle n'est pas appelée pour les cases vides dans untableau creux.

Contrairement aux autresméthodes itératives,reduce() n'accepte pas d'argumentthisArg.callbackFn est toujours appelée avec la valeurundefined pourthis, qui est remplacée parglobalThis sicallbackFn n'est pas en mode strict.

reduce() est un concept central de laprogrammation fonctionnelle : il n'est pas possible d'y modifier une valeur, donc pour accumuler toutes les valeurs d'un tableau, il faut retourner une nouvelle valeur d'accumulateur à chaque itération. Cette convention s'applique àreduce() en JavaScript : il convient d'utiliserl'opérateur de propagation ou d'autres méthodes de copie pour créer de nouveaux tableaux et objets comme accumulateur, plutôt que de modifier l'existant. Si vous décidez de modifier l'accumulateur au lieu de le copier, veillez à toujours retourner l'objet modifié dans la fonction de rappel, sinon l'itération suivante recevra la valeurundefined. Cependant, copier l'accumulateur peut entraîner une utilisation accrue de la mémoire et une dégradation des performances : voirQuand ne pas utiliser reduce() pour plus de détails. Dans ces cas, pour éviter de mauvaises performances et un code illisible, il est préférable d'utiliser une bouclefor à la place.

La méthodereduce() estgénérique. Elle attend seulement que la valeur dethis possède une propriétélength et des propriétés à clés entières.

Cas particuliers

Si le tableau ne contient qu'un seul élément (peu importe sa position) et qu'aucuneinitialValue n'est fournie, ou siinitialValue est fournie mais que le tableau est vide, la valeur unique sera retournéesans appelercallbackFn.

SiinitialValue est fournie et que le tableau n'est pas vide, la méthode reduce appellera toujours la fonction de rappel en commençant à l'index 0.

SiinitialValue n'est pas fournie, la méthode reduce se comporte différemment selon que la longueur du tableau est supérieure à 1, égale à 1 ou égale à 0, comme illustré dans l'exemple suivant :

js
const getMax = (a, b) => Math.max(a, b);// la fonction de rappel est appelée pour chaque élément du tableau à partir de l'index 0[1, 100].reduce(getMax, 50); // 100[50].reduce(getMax, 10); // 50// la fonction de rappel est appelée une fois pour l'élément à l'index 1[1, 100].reduce(getMax); // 100// la fonction de rappel n'est pas appelée[50].reduce(getMax); // 50[].reduce(getMax, 1); // 1[].reduce(getMax); // TypeError

Exemples

Fonctionnement dereduce() sans valeur initiale

Le code ci-dessous montre ce qu'il se passe si l'on appellereduce() avec un tableau et sans valeur initiale.

js
const array = [15, 16, 17, 18, 19];function reducer(accumulator, currentValue, index) {  const returns = accumulator + currentValue;  console.log(    `accumulator: ${accumulator}, currentValue: ${currentValue}, index: ${index}, returns: ${returns}`,  );  return returns;}array.reduce(reducer);

La fonction de rappel sera appelée quatre fois, avec les arguments et valeurs de retour suivants à chaque appel :

accumulatorcurrentValueindexValeur retournée
Premier appel1516131
Deuxième appel3117248
Troisième appel4818366
Quatrième appel6619485

Le paramètrearray ne change jamais pendant le processus : il reste toujours[15, 16, 17, 18, 19]. La valeur retournée parreduce() sera celle du dernier appel de la fonction de rappel (85).

Fonctionnement dereduce() avec une valeur initiale

Ici, on réduit le même tableau avec le même algorithme, mais en passant uneinitialValue de10 comme second argument àreduce() :

js
[15, 16, 17, 18, 19].reduce(  (accumulator, currentValue) => accumulator + currentValue,  10,);

La fonction de rappel sera appelée cinq fois, avec les arguments et valeurs de retour suivants à chaque appel :

accumulatorcurrentValueindexValeur retournée
Premier appel1015025
Deuxième appel2516141
Troisième appel4117258
Quatrième appel5818376
Cinquième appel7619495

La valeur retournée parreduce() dans ce cas sera95.

Additionner les valeurs d'un tableau d'objets

Pour additionner les valeurs contenues dans un tableau d'objets, ilfaut fournir uneinitialValue afin que chaque élément soit traité par la fonction.

js
const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];const sum = objects.reduce(  (accumulator, currentValue) => accumulator + currentValue.x,  0,);console.log(sum); // 6

Chaînage séquentiel de fonctions

La fonctionpipe prend une séquence de fonctions et retourne une nouvelle fonction. Lorsque cette nouvelle fonction est appelée avec un argument, la séquence de fonctions est appelée dans l'ordre, chacune recevant la valeur retournée par la fonction précédente.

js
const pipe =  (...functions) =>  (initialValue) =>    functions.reduce((acc, fn) => fn(acc), initialValue);// Briques de base pour la compositionconst double = (x) => 2 * x;const triple = (x) => 3 * x;const quadruple = (x) => 4 * x;// Fonctions composées pour multiplier par des valeurs spécifiquesconst multiply6 = pipe(double, triple);const multiply9 = pipe(triple, triple);const multiply16 = pipe(quadruple, quadruple);const multiply24 = pipe(double, triple, quadruple);// Utilisationmultiply6(6); // 36multiply9(9); // 81multiply16(16); // 256multiply24(10); // 240

Exécuter des promesses en séquence

Lechaînage de promesses est essentiellement un chaînage de fonctions comme démontré dans la section précédente, mais réalisé de façon asynchrone.

js
// À comparer avec pipe : fn(acc) devient acc.then(fn),// et initialValue est garanti d'être une promesseconst asyncPipe =  (...functions) =>  (initialValue) =>    functions.reduce((acc, fn) => acc.then(fn), Promise.resolve(initialValue));// Briques de base pour la compositionconst p1 = async (a) => a * 5;const p2 = async (a) => a * 2;// Les fonctions composées peuvent aussi retourner des non-promesses, car les valeurs sont// toutes enveloppées dans des promesses au finalconst f3 = (a) => a * 3;const p4 = async (a) => a * 4;asyncPipe(p1, p2, f3, p4)(10).then(console.log); // 1200

asyncPipe peut aussi être implémenté avecasync/await, ce qui montre mieux sa similarité avecpipe :

js
const asyncPipe =  (...functions) =>  (initialValue) =>    functions.reduce(async (acc, fn) => fn(await acc), initialValue);

Utiliserreduce() avec des tableaux creux

reduce() ignore les éléments manquants dans les tableaux creux, mais n'ignore pas les valeursundefined.

js
console.log([1, 2, , 4].reduce((a, b) => a + b)); // 7console.log([1, 2, undefined, 4].reduce((a, b) => a + b)); // NaN

Appelerreduce() sur des objets ressemblant à des tableaux

La méthodereduce() lit la propriétélength dethis puis accède à chaque propriété dont la clé est un entier non négatif inférieur àlength.

js
const objetSimilaireTableau = {  length: 3,  0: 2,  1: 3,  2: 4,  3: 99, // ignoré par reduce() car length vaut 3};console.log(  Array.prototype.reduce.call(objetSimilaireTableau, (x, y) => x + y),);// 9

Quand ne pas utiliserreduce()

Les fonctions d'ordre supérieur polyvalentes commereduce() peuvent être puissantes mais parfois difficiles à comprendre, surtout pour les développeur·euse·s JavaScript moins expérimenté·e·s. Si le code est plus clair avec d'autres méthodes de tableau, il faut peser la lisibilité face aux autres avantages dereduce().

Notez quereduce() est toujours équivalent à une bouclefor...of, sauf qu'au lieu de modifier une variable dans la portée supérieure, on retourne la nouvelle valeur à chaque itération :

js
const val = array.reduce((acc, cur) => update(acc, cur), initialValue);// Équivalent à :let val = initialValue;for (const cur of array) {  val = update(val, cur);}

Comme indiqué précédemment, la raison pour laquelle on peut vouloir utiliserreduce() est d'imiter les pratiques de programmation fonctionnelle avec des données immuables. Ainsi, les développeur·euse·s qui respectent l'immuabilité de l'accumulateur copient souvent tout l'accumulateur à chaque itération, comme ceci :

js
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];const countedNames = names.reduce((allNames, name) => {  const currCount = Object.hasOwn(allNames, name) ? allNames[name] : 0;  return {    ...allNames,    [name]: currCount + 1,  };}, {});

Ce code est inefficace, car chaque itération doit copier tout l'objetallNames, qui peut être volumineux selon le nombre de noms uniques. Ce code a une complexité dans le pire des cas enO(N^2), oùN est la longueur denames.

Une meilleure alternative consiste àmuter l'objetallNames à chaque itération. Cependant, siallNames est de toute façon modifié, il peut être préférable de convertir lereduce() en bouclefor, ce qui est bien plus lisible :

js
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];const countedNames = names.reduce((allNames, name) => {  const currCount = allNames[name] ?? 0;  allNames[name] = currCount + 1;  // retourner allNames, sinon l'itération suivante reçoit undefined  return allNames;}, Object.create(null));
js
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];const countedNames = Object.create(null);for (const name of names) {  const currCount = countedNames[name] ?? 0;  countedNames[name] = currCount + 1;}

Ainsi, si votre accumulateur est un tableau ou un objet et que vous le copiez à chaque itération, vous pouvez accidentellement introduire une complexité quadratique dans votre code, ce qui dégradera rapidement les performances sur de grandes données. Cela s'est produit dans du code réel : voir par exempleRendre Tanstack Table 1000x plus rapide avec un changement d'une ligne(angl.).

Quelques cas d'usage acceptables dereduce() sont donnés ci-dessus (notamment la somme d'un tableau, le chaînage de promesses et le chaînage de fonctions). Il existe d'autres cas où de meilleures alternatives àreduce() existent.

  • Aplatir un tableau de tableaux. Utilisez plutôtflat().

    js
    const flattened = array.reduce((acc, cur) => acc.concat(cur), []);
    js
    const flattened = array.flat();
  • Regrouper des objets selon une propriété. Utilisez plutôtObject.groupBy().

    js
    const groups = array.reduce((acc, obj) => {  const key = obj.name;  const curGroup = acc[key] ?? [];  return { ...acc, [key]: [...curGroup, obj] };}, {});
    js
    const groups = Object.groupBy(array, (obj) => obj.name);
  • Concaténer des tableaux contenus dans un tableau d'objets. Utilisez plutôtflatMap().

    js
    const friends = [  { name: "Anna", books: ["Bible", "Harry Potter"] },  { name: "Bob", books: ["Guerre et Paix", "Roméo et Juliette"] },  { name: "Alice", books: ["Le Seigneur des anneaux", "Shining"] },];const allBooks = friends.reduce((acc, cur) => [...acc, ...cur.books], []);
    js
    const allBooks = friends.flatMap((person) => person.books);
  • Retirer les doublons d'un tableau. Utilisez plutôtSet etArray.from().

    js
    const uniqArray = array.reduce(  (acc, cur) => (acc.includes(cur) ? acc : [...acc, cur]),  [],);
    js
    const uniqArray = Array.from(new Set(array));
  • Éliminer ou ajouter des éléments dans un tableau. Utilisez plutôtflatMap().

    js
    // Prend un tableau de nombres et sépare les carrés parfaits en leurs racines carréesconst roots = array.reduce((acc, cur) => {  if (cur < 0) return acc;  const root = Math.sqrt(cur);  if (Number.isInteger(root)) return [...acc, root, root];  return [...acc, cur];}, []);
    js
    const roots = array.flatMap((val) => {  if (val < 0) return [];  const root = Math.sqrt(val);  if (Number.isInteger(root)) return [root, root];  return [val];});

    Si vous ne faites qu'éliminer des éléments d'un tableau, vous pouvez aussi utiliserfilter().

  • Rechercher des éléments ou tester si des éléments satisfont une condition. Utilisez plutôtfind() etfindIndex() ousome() etevery(). Ces méthodes ont l'avantage supplémentaire de retourner le résultat dès qu'il est certain, sans parcourir tout le tableau.

    js
    const allEven = array.reduce((acc, cur) => acc && cur % 2 === 0, true);
    js
    const allEven = array.every((val) => val % 2 === 0);

Dans les cas oùreduce() est le meilleur choix, une bonne documentation et des noms de variables sémantiques peuvent aider à atténuer les problèmes de lisibilité.

Spécifications

Specification
ECMAScript® 2026 Language Specification
# sec-array.prototype.reduce

Compatibilité des navigateurs

Voir aussi

Help improve MDN

Learn how to contribute

Cette page a été modifiée le par lescontributeurs du MDN.


[8]ページ先頭

©2009-2025 Movatter.jp