自己手写代码实现一个方法,需要先了解原方法的实现原理:这是开发文档地址
reduce 语法: arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)
参数解析:
callback
必需。用于执行每个数组元素的函数。函数参数:可加入四个参数:
accumulator
是上一次计算后所回传的累加数值。
currentValue
遍历数组所在当前元素。
currentIndex(可选)
如果传initialValue,则由索引0之元素开始,若无则自索引1之元素开始。
array(可选)
当前元素所属的数组
initialValue(可选)
传递给函数的初始值
举例了解大概流程:
[1,2,3].reduce((a,b) => a+b,0)
[1, 2, 3] // 取出 1 + 2 ,填回 3
[3, 3] // 取出 3 + 3 ,填回 6
[6] // 最终结果为 6
方法1:根据上面的逻辑简单实现:
const fn = function (totalVal, curVal, i, arr) {
return totalVal + curVal
};
Array.prototype.myReduce = function fakeReduce(fn, base) {
if (typeof fn !== 'function') {
throw TypeError(fn + ' is not a function')
}
// let arr = base ? this.unshift(base) : this;// 首进,返回新数组的长度,影响原数组 故不能这么写
let initialArr = this;
let arr = initialArr.concat(); //得到副本
if (base !== undefined) arr.unshift(base); // 当存在归并基础值的参数时,将其从数组首部推入
let index = 0;
if (arr.length == 0) {
throw TypeError("Array can not be empty");
}
if (arr.length == 1) {
return arr[0];
}
while (arr.length > 2) {
index = initialArr.length - arr.length + 1;//有传递初始值,当前元素使用arr[0],否则使用arr[1],
let newValue = fn.call(null, arr[0], arr[1], index, initialArr);
arr.splice(0, 2, newValue);
}
//此时数组剩下最后两个元素,返回结果即可
index += 1;
let result = fn.call(null, arr[0], arr[1], index, initialArr);
return result;
};
let arr = [2,22,33];
console.log(arr.reduce(fn, 0));
console.log("====my:====")
console.log(arr.myReduce(fn, 0));
方法2:实现递归实现:
const fn = function (totalVal, curVal, i, arr) {
return totalVal + curVal
};
const reduceHelper = (fn, acc, idx, array) => {
if (array.length === 0) return acc
const [head, ...tail] = array
idx++
return reduceHelper(fn, fn(acc, head, idx, array), idx, tail)
}
Array.prototype.myReduce = function (cb, initialValue) {
if (typeof fn !== 'function') {
throw TypeError(fn + ' is not a function')
}
if (this.length === 0 && initialValue === undefined) {
throw TypeError('Reduce of empty array with no initial value')
}
const array = this
const [head, ...tail] = array
const startIndex = initialValue === undefined ? 0 : 1
return initialValue === undefined ? reduceHelper(cb, head, startIndex, tail) : reduceHelper(cb, initialValue, startIndex, array)
}
let arr = [2,22,33];
console.log(arr.reduce(fn, 0));
console.log("====my:====")
console.log(arr.myReduce(fn, 0));
方法3:重构非递归实现:
const fn = function (totalVal, curVal, i, arr) {
return totalVal + curVal
};
Array.prototype.myReduce = function (fn, initTotalVal) {
if (typeof fn !== 'function') {
throw TypeError(fn + ' is not a function')
}
if (this.length === 0 && initTotalVal === undefined) {
throw TypeError('Reduce of empty array with no initial value')
}
const array = this;
let index = initTotalVal === undefined ? 1 : 0;
let acc = initTotalVal === undefined ? array[0] : initTotalVal;
for (let i = index; i < array.length; i++) {
acc = fn(acc, array[i], index, array)
}
return acc
}
let arr = [];
console.log(arr.reduce(fn, false));
console.log("====my:====")
console.log(arr.myReduce(fn, false));
参考文章地址