reduce相关语法
arr.reduce(callbackFn, [initalValue]);
callbackFn:reducer函数
包含四个参数:
- previousValue:上一次调用callbackFn的返回值,在第一次调用的时候,如果指定了initalValue,则其值为initalValue,否则为数组索引为0的元素
- currentValue:数组正在处理的元素,在第一次调用的时候,如果指定了initalValue,其值为数组索引为0的元素,否则为数组索引为1的元素
- currentIndex:数组正在处理的元素的索引,如果指定了initalValue,起始索引为0,否则为1
- array:用于遍历的数组
initalValue(可选):
- 第一次调用时作为previousValue的值,这是一个可选的参数
注意点
- reducer不会改变原数组
- reducer中的callbackFn需要返回值(因为需要作为下一次调用的previousValue)
reduce源码实现
实现思路
- 类型检验:回调函数是否对函数,数组是否为空等
- 初始值提供检测,用于确定初始previousValue的值
- 返回累计值
代码实现
Array.prototype.myReduce = function(callbackFn, initalValue) {
// Step1:类型检验
if (this === null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
};
if (typeof callbackFn !== 'function') {
throw new TypeError('Callback must be a function');
};
const obj = Object(this); // #1
const lenValue = obj.length;
const len = lenValue >>> 0; // #2
if (len === 0 && !initalValue) {
throw new TypeError('The array contains no elements and initalValue is not provided')
};
let k = 0;
let accumulator; // 这里变量名为accumulator十分贴合reduce函数作为累加器使用的性质
// Step2:初始accumulator的值确定
if (initalValue) {
// 有initalValue,accumulator就为初始值
accumulator = initalValue;
} else {
// 没有initalValue,就需要把数组的第一个值即arr[0]作为初始值
// 这里别着急,我们还需要做进一步检测
let kPressent = false; // #3
while (!kPressent && k < len) {
const pK = String(k);
kPressent = obj.hasOwnProperty(pK); // 第一个检测到合法的元素作为
if (kPressent) {
accumulator = obj[pK];
};
k++;
};
if (!kPressent) {
// 数组没有合法元素,报错
throw new TypeError('The array contains error elements');
};
};
// 到这里我们已经确定了accumulator的值
// 注意:如果initalValue存在,k=0,如果不存在,则accumulator = 数组第一个合法元素,k因为之前也++了,k=k
// Step3:确定callback的返回值
while (k < len) {
if (k in obj){
// # 4
accumulator = callbackFn(accumulator, obj[k], k, obj);
};
k++;
};
return accumulator