Reducing is the most general of the functional array methods. You take an array, and get back any one thing. I can be an array, an object, a number, a string, any damn thing. It can even replicate a filter, returning an array with elements removed, or a map that can even add elements. It's pretty cool. However, there are some eccentricities with the built in `[].reduce` function, making using it improperly one of the JavaScript Common Pitfalls
First off it's an Array.prototype method. Meaning you have to do a little juggling to use it on array like objects. Not a huge concern, but something to watch out for.
Secondly it works left to right. If order matters in your reduce that is important to know. If you need to work right to left, there is a corresponding `[].reduceRight`.
//broken var arr = [ 2, 4, 8, 64 ] var a = arr.reduce(divide) console.log(a) // 0.0009765625 // order matters var b = arr.reduceRight(divide) console.log(b) // 1 function divide (a, b) { return a/b }
By default reduce provides the first element of the array as the aggregate, if one isn't provided. This can lead to extremely hard to debug valid, but nonsensical results.
// broken var arr = [ 100, 10, 1 ] var a = arr.reduce(subtract) console.log(a) // 89 // or did I want this? var b = arr.reduce(subtract, 0) // initial reducer console.log(b) // -111 function subtract (a, b) { return a - b }
But, the most common error is not returning the up to date result from your function. It's easy to think of the aggregate as always being there and the same if you are mostly using it as a reference to the same object each time, the same one that was initially passed. But some times it's a new value each iteration, not the last one but mutated. And if you ever forget to return it, it's undefined in the next go around.
//broken var arr = [ 'Larry', 'Curly', 'Moe' ] var a = arr.reduce(badAdd) console.log(a) // undefined var b = arr.reduce(add) console.log(b) // Larry, Curly, Moe function badAdd (a, b) { a + ', ' + b } function add (a, b) { return a + ', ' + b }
So, happy reducing, but be careful of the sharp edges!
var arr = [ { name: 'Donatello', color: 'purple'} , { name: 'Michelangelo', color: 'orange'} , { name: 'Raphael', color: 'red'} , { name: 'Leonardo', color: 'blue'} ] var a = arr.reduce(colorToName, {}) console.log(a) //{ purple: 'Donatello', // orange: 'Michelangelo', // red: 'Raphael', // blue: 'Leonardo' } function colorToName (a, b) { a[b.color] = b.name return a }