26 May 2013

JavaScript reduce

A while ago I was commenting on a Forrsters reduce (sum) function that he posted for review. I pointed him to a method in underscore.js called _.reduce that did something similar. In doing so, however, I felt bad just saying “here, just look at this” without really understanding the internals of what I was putting forward. So I read the underscore.js annotated source for reduce and learnt some pretty neat things.

The underscore version of the (native in ECMAScript 5) method reduce (_.reduce) uses the native method as a fallback and patches in support for older browsers whose Arrays do not have reduce in the prototype chain.

It works like this. You pass it 3 parameters, an array to loop over, a function to call on each element in said array and a starting value for the memory parameter.

Each iteration sets the memory parameter as the return value of the function passed in.

example:

var logSum = function(memoryElement, elementToAdd){
    console.log(memoryElement+elementToAdd);
}

var input = [1,2,3,4];
var output = _.reduce(input, logSum, 0);

Each iteration will look like this:

Iteration | memory parameter | value to add  | output

Init:     |        0         |       1       |    1
1:        |        1         |       2       |    3
2:        |        3         |       3       |    6
3:        |        6         |       4       |    10

This will yield 10, as expected.

JSBin

This will help make for loops look a little more presentable in the future. Especially ones that operate on themselves.

Rather than doing something like:

var input = [1,2,3,4];
var result = 0;
for(var i = 0; i < input.length; i++){
    result += input[i];
}
console.log(result) // 10

We can make that more readable (and potentially DRYer) for future us like so:

var values = [1,2,3,4];
var result = 0;
var sum = function(a,b){a+b}
result = _.reduce(values, sum, 0); // 10