reduce:累加器(accumulator)javascript
// 判断非空
const isDef = function(o){
return o !== undefined && o !== null
}
/** * fn 函数 * @param { * } total 初始值(计算结束后的返回值) * @param { * } currentValue 当前元素 * @param { Number } currentIndex 当前元素的索引 * @param { Array } arr 当前元素所属的数组对象 */
// Array的prototype声明$reduce
Array.prototype.$reduce = function(fn, tar){
let len = this.length, // 目标数组长度
res, // 数组
i = 0; // 初始index
if (isDef(tar)) {
// 有第二个参数,total为初始值
res = tar
} else {
// 没有第二个参数,初始值为数组第一项
res = this[0]
// 因为第一项为初始值,就从第二项开始累计
i++
}
// 循环数组
while (i < len) {
// 把算的值传入fn第一个参数
res = fn(res, this[i], i++, this)
}
return res
}
复制代码
应用java
[1, 2, 3, 4, 5].$reduce((total, currentValue, currentIndex, arr) => {
console.log(total, currentValue, currentIndex, arr)
return total + currentValue;
}, 0) // => 15
// 0 1 0 [ 1, 2, 3, 4, 5 ]
// 1 2 1 [ 1, 2, 3, 4, 5 ]
// 3 3 2 [ 1, 2, 3, 4, 5 ]
// 6 4 3 [ 1, 2, 3, 4, 5 ]
// 10 5 4 [ 1, 2, 3, 4, 5 ]
复制代码
返回一个函数,把this改成返回函数的参数(arr)git
// reduce : ((a, b) → a) → a → [b] → a
const reduce = function(fn, tar){
const _isDef = function(o){
return o !== undefined && o !== null
}
return function(arr){
let len = arr.length,
res,
i = 0;
if (_isDef(tar)) {
res = tar
} else {
res = arr[0]
i++
}
while (i < len) {
res = fn(res, arr[i], i++, arr)
}
return res
}
}
// 求和
const sum = reduce((a, b) => a + b, 0)
sum([1, 2, 3, 4, 5]) // 15
// 求乘积
const product = reduce((a, b) => a * b)
product([1, 2, 3, 4, 5]) // 120
// 求对象数组某元素的某一项和
const inSum = reduce((a, { score }) => a + score, 0)
inSum([{ score: 1 }, { score: 2 }, { score: 3 }]) // 6
复制代码
ps. 函数式编程最好的参考书: legacy.gitbook.com/book/llh911…编程