TL; DR, définissez la valeur initiale
Utiliser la déstructuration
arr.reduce( ( sum, { x } ) => sum + x , 0)
Sans déstructuration
arr.reduce( ( sum , cur ) => sum + cur.x , 0)
Avec Typescript
arr.reduce( ( sum, { x } : { x: number } ) => sum + x , 0)
Essayons la méthode de déstructuration:
const arr = [ { x: 1 }, { x: 2 }, { x: 4 } ]
const result = arr.reduce( ( sum, { x } ) => sum + x , 0)
console.log( result ) // 7
La clé de ceci est la définition de la valeur initiale. La valeur de retour devient le premier paramètre de la prochaine itération.
La technique utilisée dans la première réponse n'est pas idiomatique
La réponse acceptée propose de NE PAS passer la valeur "facultative". C'est faux, car la manière idiomatique est que le deuxième paramètre soit toujours inclus. Pourquoi? Trois raisons:
1. Dangereux
- Ne pas transmettre la valeur initiale est dangereux et peut créer des effets secondaires et des mutations si la fonction de rappel est négligente.
Voir
const badCallback = (a,i) => Object.assign(a,i)
const foo = [ { a: 1 }, { b: 2 }, { c: 3 } ]
const bar = foo.reduce( badCallback ) // bad use of Object.assign
// Look, we've tampered with the original array
foo // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
Si toutefois nous l'avions fait de cette façon, avec la valeur initiale:
const bar = foo.reduce( badCallback, {})
// foo is still OK
foo // { a: 1, b: 2, c: 3 }
Pour l'enregistrement, sauf si vous avez l'intention de muter l'objet d'origine, définissez le premier paramètre de Object.assign
sur un objet vide. Comme ceci: Object.assign({}, a, b, c)
.
2 - Meilleure inférence de type
- Lorsque vous utilisez un outil comme Typescript ou un éditeur comme VS Code, vous avez l'avantage de dire au compilateur l'initiale et il peut détecter des erreurs si vous le faites mal. Si vous ne définissez pas la valeur initiale, dans de nombreuses situations, elle pourrait ne pas être en mesure de deviner et vous pourriez vous retrouver avec des erreurs d'exécution effrayantes.
3 - Respectez les foncteurs
- JavaScript brille mieux lorsque son enfant fonctionnel intérieur est libéré. Dans le monde fonctionnel, il existe une norme sur la façon dont vous "pliez" ou reduce
un tableau. Lorsque vous pliez ou appliquez un catamorphisme au tableau, vous prenez les valeurs de ce tableau pour construire un nouveau type. Vous devez communiquer le type résultant - vous devez le faire même si le type final est celui des valeurs du tableau, d'un autre tableau ou de tout autre type.
Réfléchissons-y d'une autre manière. En JavaScript, les fonctions peuvent être transmises comme des données, c'est ainsi que fonctionnent les rappels, quel est le résultat du code suivant?
[1,2,3].reduce(callback)
Va-t-il retourner un numéro? Un objet? Cela rend plus clair
[1,2,3].reduce(callback,0)
En savoir plus sur les spécifications de programmation fonctionnelle ici: https://github.com/fantasyland/fantasy-land#foldable
Un peu plus de contexte
La reduce
méthode prend deux paramètres,
Array.prototype.reduce( callback, initialItem )
La callback
fonction prend les paramètres suivants
(accumulator, itemInArray, indexInArray, entireArray) => { /* do stuff */ }
Pour la première itération,
Si initialItem
est fourni, la reduce
fonction transmet le en initialItem
tant que accumulator
et le premier élément du tableau en tant que itemInArray
.
Si initialItem
n'est pas fourni, la reduce
fonction transmet le premier élément du tableau en tant que initialItem
et le deuxième élément du tableau en tant itemInArray
que comportement déroutant.
J'enseigne et recommande de toujours régler la valeur initiale de réduire.
Vous pouvez consulter la documentation sur:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
J'espère que cela t'aides!
arr.reduce(function(a,b){return a + b})
dans le deuxième exemple.