持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
前言
个人认为 reduce() 方法是 Array.pototype 上所有高阶函数中,功能最为强大,抛去性能之间的区别, 其他的高阶函数能实现的功能,它都可以做到,而它能做到,其他高阶函数不一定能够做到。
如果能够手写实现了 reduce ,基本都可以实现 Array.pototype 的其他高阶函数。
实现的基本思路
reduce 的本质还是遍历数组,不过是每次遍历都调用传入的回调函数 callback ,然后保存 callback 的返回值,作为下一次执行 callback 的参数,直到数组遍历完成。
代码
首先定义方法,包括它的参数和返回值。
主要接受两个参数:一个是每次遍历元素执行的回调函数 callback;一个是上一次的执行结果 preValue,这个参数是可选的。
返回值就是返回最终的 preValue,代码如下:
/**
* 手写reduce
* @param { Function } callback 处理函数
* @param { any } preValue 上一次返回结果
* @returns { any }
*/
Array.prototype.myReduce = function (callback, preValue) {
return preValue
}
然后就是参数检测,callback 必须是函数,而 preValue 可以是任何值,不许检测,代码如下:
if (typeof callback !== 'function') {
throw new Error(`${callback} is not a function !`)
}
接着就是对 preValue 进行处理,如果使用 reduce 时没有传入第二个参数,则 preValue 默认是数组的第一个元素,第一次遍历是从数组的第二个元素开始,代码如下:
// 当前遍历索引
let index = 0
// 数组长度
let len = this.length
// 如果 preValue 没有传入,当前索引变更为 1,preValue 变更为 数组的第一个元素
if (preValue === undefined) {
index = 1
preValue = this[0]
}
接下来就是遍历数组,步骤如下:
-
- 每遍历一个元素,执行一次回调函数
callback;
- 每遍历一个元素,执行一次回调函数
-
- 回调函数
callback,传入四个参数:上一次的返回值、当前元素、当前索引、被遍历的数组;
- 回调函数
-
callback的返回值作为下一次执行callback的参数
-
- 数组遍历完成,返回
preValue;
- 数组遍历完成,返回
代码如下:
// 逐层遍历
for (; index < len; index++) {
/**
* 四个参数:
* 上一次的返回值
* 当前元素
* 当前索引
* 遍历的数组
*/
preValue = callback(preValue, this[index], index, this)
}
return preValue
完整代码如下:
Array.prototype.myReduce = function (callback, preValue) {
if (typeof callback !== 'function') {
throw new Error(`${callback} is not a function !`)
}
let index = 0
let len = this.length
if (preValue === undefined || preValue === null) {
index = 1
preValue = this[0]
}
for (; index < len; index++) {
preValue = callback(preValue, this[index], index, this)
}
return preValue
}
和原生的 reduce 同时执行,简单测试一下:
const arr = [1, 2, 3, 4, 5, 6]
console.log('Array.prototype.reduce 1:', arr.reduce((a, b) => a + b))
console.log('Array.prototype.reduce 2:', arr.reduce((a, b) => a + b, ''))
console.log('my reduce 1:', arr.myReduce((a, b) => a + b))
console.log('my reduce 2:', arr.myReduce((a, b) => a + b, ''))
至此,基本完成了。