15.4.4.21 Array.prototype.reduce(callbackfn[, initialValue])

2010-07-05

mixed Array.prototype.reduce(callbackfn:function[, initialValue:mixed=undefined]) throws TypeError

Reduce the array to a single value, processing the elements left to right (see reduceRight for other direction) skipping missing elements. The callback is called for every element also supplying the previous value. The result of reduce is the result of the last call to callbackfn.

The callback callbackfn should match this fingerprint: mixed function(previousValue:mixed, currentvalue:mixed, currentIndex:int, object:object).

The this value will be coerced into an object, if initialValue was supplied it is not changed. If initialValue is not given it is set to the first (existing) element in the array. If initialValue is not given and the array has no values a TypeError is thrown.

The reduce method does not change the array it works on.

The range of reduce is determined before actually calling the callbackfn the first time. The value passed on is the value of the array at the time of calling callbackfn (so if callbackfn changes it, the new value is supplied). Deleted elements are skipped. Elements added beyond the initial length of the array during by callbackfn are not processed.

Array.prototype.reduce.length = 1

Code: (Meta Ecma)
Array.prototype.reduce = function(callbackfn,initialValue){
var O = ToObject(this);
var lenValue = O.[[Get]]("length");
var len = ToUint32(lenValue);
if (!IsCallable(callbackfn)) throw TypeError;
if (arguments.length < 2 && len == 0) throw TypeError;
var k = 0;
if (arguments.length >= 2) var accumulator = initialValue;
else {
// get the first element that exists
var kPresent = false;
while (!kPresent && k < len) {
var Pk = ToString(k);
var kPresent = O.[[HasProperty]](Pk);
if (kPresent) {
var accumulator = O.[[Get]](Pk);
}
++k;
}
if (!kPresent) throw TypeError;
}
// note: uses same k from above, might not be zero
while (k < len) {
var Pk = ToString(k);
var kPresent = O.[[HasProperty]](Pk);
if (kPresent) {
var kValue = O.[[Get]](Pk);
var accumulator = callbackfn.[[Call]](undefined, [kValue, k, O]);
}
++k;
}
return accumulator;
}