原生的reduce方法只適用于數(shù)組蹋偏,且方向固定為從左向右吆倦。
underscore中的reduce與reduceRight分別支持兩個方向的迭代异剥,且支持對對象的操作送讲。
_.reduce = _.foldl = _.inject = createReduce(1);
_.reduceRight = _.foldr = createReduce(-1);
其底層實現(xiàn)均為createReduce方法。
createReduce
//dir決定迭代方向伟恶,-1為從右向左碴开,1為從左向右
var createReduce = function(dir) {
// Wrap code that reassigns argument variables in a separate function than
// the one that accesses `arguments.length` to avoid a perf hit. (#1991)
//這里是迭代的核心函數(shù)
var reducer = function(obj, iteratee, memo, initial) {
//處理數(shù)組與對象的不同
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
//迭代方向
index = dir > 0 ? 0 : length - 1;
//是否提供最初與數(shù)組或?qū)ο筮M行迭代的數(shù)據(jù)
if (!initial) {
memo = obj[keys ? keys[index] : index];
//需要將起始位置向迭代方向移動一位
index += dir;
}
//迭代
for (; index >= 0 && index < length; index += dir) {
var currentKey = keys ? keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
return memo;
};
return function(obj, iteratee, memo, context) {
//initial變量標識是否提供最初的迭代數(shù)據(jù)
var initial = arguments.length >= 3;
return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
};
};