重写数组reduce

108 阅读1分钟

需要注意的点

  1. reduce 的 callback 接收三个参数,分别是上一轮结果的值,初始值和当前循环的下标
  2. reduce 第一个参数不是函数,报类型错误 "xxx is not a function"
  3. reduce 的目标数组为空数组,若传递了初始值,则直接返回初始值,不然报类型错误 "Reduce of empty array with no initial value"
  4. reduce 的目标数组只有一个元素,返回该元素,不进行迭代。
Array.prototype._reduce = function reduce(cb, initial) {
    // this 即为需要迭代的数组
    // 如果传递了第二个参数 则从数组第一个元素开始循环
    let self = this,
        i = 0, 
        result = initial,
        len = self.length,
        isInit = typeof initial === 'undefined' ? false : true; 

    if (typeof cb !== 'function') throw new TypeError(`${ cb } is not a function!`)

    // 数组为空且没有初始值 报错
    if (len === 0 && !isInit) throw newTypeError('Reduce of empty array with no initial value');

    // 数组为空 有初始值 返回初始值
    if (len === 0 && isInit) return initial;

    // 数组有一项 且没有初始值
    if (len === 1 && !isInit) return self[0];


    // 没传递初始值 从数组第二个开始循环 第一个元素作为初始的 result
    if (!isInit) {
        result = self[0]; 
        i = 1;
    }

    for (; i < self.length; i++) {
        result = cb(result, self[i], i);
    }

    return result;
}

let arr = [1, 2, 3, 4];
let total = arr._reduce(function(prev, next) {
	return prev + next
}, 0);
console.log(total);

来一版纯净代码:

Array.prototype._reduce = function reduce(cb, initial) {
    let self = this,
        i = 0, 
        result = initial,
        len = self.length,
        isInit = typeof initial === 'undefined' ? false : true; 

    if (typeof cb !== 'function') {
        throw new TypeError(`${ cb } is not a function!`);
    }

    if (len === 0 && !isInit) {
        throw newTypeError('Reduce of empty array with no initial value');
    }

    if (len === 0 && isInit) return initial;

    if (len === 1 && !isInit) return self[0];

    if (!isInit) {
        result = self[0]; 
        i = 1;
    }

    for (; i < self.length; i++) {
        result = cb(result, self[i], i);
    }

    return result;
}

let arr = [1, 2, 3, 4];
let total = arr._reduce(function(prev, next) {
	return prev + next
}, 0);
console.log(total);