Javascript reduce gotcha - skips first iteration?

Viewed 3564

Why does javascript's implementation of reduce skip execution for the first iteration?

[1,2,3].reduce((acc, val) => {
    console.log('acc',acc);
    console.log('val',val)
    return acc + val;
});
// acc 1
// val 2
// acc 3
// val 3
// 6

I notice that the first statement execution never runs (in this case, I would have expected there to be 6 console logs, 2 for each element). This was very unexpected behavior when I was trying to execute a function with a side effect within each iteration with reduce.

In other languages that I've used, every iteration of the list passed executes. Are there examples otherwise?

Why does this happen and why is the implementation of javascript's native Array reduce like this?

========================= EDIT 1/Solution ========================
To make sure it goes through the first iteration, give it an initial value (the 2nd argument here/ 0 in this case)

[1,2,3].reduce((acc, val) => { console.log('acc',acc); console.log('val',val) return acc + val; }, 0);

1 Answers

That is because of the fact that on every iteration, the first value is treated as a return value (or the accumulator).

Straight from here, you can see

The accumulator accumulates the callback's return values; it is the accumulated value previously returned in the last invocation of the callback, or initialValue, if supplied (see below).


If we look at the source code here, we can see how it's implemented:

Array.prototype.myReduce = function(callback, initialVal) {
    var accumulator = (initialVal === undefined) ? undefined : initialVal;
    for (var i = 0; i < this.length; i++) {
        if (accumulator !== undefined)
            accumulator = callback.call(undefined, accumulator, this[i], i, this);
        else
            accumulator = this[i];
    }
    return accumulator;
};

In the else structure, we can see that if the value is undefined, we set it to the i-th subindex in the array; which, for the first iteration, is the first one. After that, it becomes the callback (return) value of the iterations which follow.

If you want, you can backtrack and check the output.

Related