# Array.prototype.reduce()
其中有几个核心要点:
- 初始值不传
- 回调函数的参数,返回值处理
Array.prototype.reduce = function (callback, initialValue) {
// 处理数组类型异常
if (this === null || this === undefined) {
throw new TypeError("Cannot read property 'filter' of null or undefined")
}
// 处理回调类型异常
if (Object.prototype.toString.call(callback) !== '[object Function]') {
throw new TypeError(callback + ' is not a function')
}
let O = Object(this),
len = O.length >>> 0,
k = 0,
accumulator = initialValue;
// 第一个有效值作为累加器的初始值
if (accumulator === undefined) {
for (; k < len; K++) {
if (k in O) {
accumulator = O[k];
k++;
break;
}
}
// 超出数组界限,则TypeError
if (k > len || len === 0) {
throw new Error('Each element of the array is empty')
}
}
for (; k < len; k++) {
if (k in O) {
// accumulator: 参数传递 实现累加
accumulator = callback.call(undefined, accumulator, O[k], O)
}
}
return accumulator
}
奉上V8源码,以供大家检查:
function ArrayReduce(callback, current) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reduce");
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
return InnerArrayReduce(callback, current, array, length,
arguments.length);
}
function InnerArrayReduce(callback, current, array, length, argumentsLength) {
if (!IS_CALLABLE(callback)) {
throw %make_type_error(kCalledNonCallable, callback);
}
var i = 0;
find_initial: if (argumentsLength < 2) {
for (; i < length; i++) {
if (i in array) {
current = array[i++];
break find_initial;
}
}
throw %make_type_error(kReduceNoInitial);
}
for (; i < length; i++) {
if (i in array) {
var element = array[i];
current = callback(current, element, i, array);
}
}
return current;
}
参考: