前言
对于 reduce,可能之前对于他的用法只是用于累加,但其实他的真正用途适用于作为一个高阶函数,用于实现函数式编程里的 compose
compose 的个人理解
创建一个函数,最少接收两个参数,一个函数数组,一个初始参数,依次执行函数数组,下一个函数的第一个参数是上一个的结果,初始参数是第一个函数的第一个参数。
lodash 实现
reduce
<!– 接收 4 个参数,第一个是要执行的数组,第二个是回调函数,第三个是初始参数,第 4 个是是否跳过第一个回调并拿第一个参数当做下一个回调的参数 –>
function reduce(collection, iteratee, accumulator) {
const func = Array.isArray(collection) ? arrayReduce : baseReduce
const initAccum = arguments.length < 3
<!– baseEach 是当 collection 不是数组时的实现 –>
return func(collection, iteratee, accumulator, initAccum, baseEach)
}
arrayReduce
function arrayReduce(array, iteratee, accumulator, initAccum) {
let index = -1
const length = array == null ? 0 : array.length
if (initAccum && length) {
accumulator = array[++index]
}
// 当 initAccum 为 true 时,从下标为 1 的开始运行
while (++index < length) {
accumulator = iteratee(accumulator, array[index], index, array)
}
return accumulator
}
baseReduce
<!– 当 collection 是对象时的实现 –>
function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
eachFunc(collection, (value, index, collection) => {
accumulator = initAccum
? (initAccum = false, value)
: iteratee(accumulator, value, index, collection)
})
return accumulator
}
baseEach
<!– 对 collection 是不同类型的处理 –>
function baseEach(collection, iteratee) {
if (collection == null) {
return collection
}
<!– 判断是不是非常规的 Array,例如 arguments –>
if (!isArrayLike(collection)) {
<!– 这里的具体就是跑了个 for –>
return baseForOwn(collection, iteratee)
}
const length = collection.length
const iterable = Object(collection)
let index = -1
while (++index < length) {
<!– 这里的具体就是跑了个 for,initAccum 为 true 时第一次跳过 –>
if (iteratee(iterable[index], index, iterable) === false) {
break
}
}
return collection
}