Underscore 源码学习 (四) - Reduce

终于看完了 Underscore 的集合部分了,看 Underscore 源码真的是长见识了,感觉真的受益匪浅。
但是集合里面方法也挺多的,我都不知道该拿哪些出来讲下,最近接触了 Redux,就说下 createReduce 这个方法吧,为后面讲 Redux 做个铺垫。
先看源码

var createReduce = function(dir) {
  var reducer = function(obj, iteratee, memo, initial) {
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length,
        index = dir > 0 ? 0 : length - 1;
    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) {
    var initial = arguments.length >= 3;
    return reducer(obj, opitimizeCb(iteratee, context, 4), memo, initial);
  };
};

这是 reduce 函数的工厂函数,用于生成一个 reducer ,dir 是决定方向用的。
我们从最后一个 return 开始看起,即

return function(obj, iteratee, memo, context) {
  var initial = arguments.length >= 3;
  return reducer(obj, opitimizeCb(iteratee, context, 4), memo, initial);
};

我们使用 reduce 的时候,如果没有指定 memo 值,这时候参数个数只有两个即 obj 和 iteratee,所以 initial 为 false 表示没有初始化。对于没初始的情况,就是增加了一个 if 语句里面的内容而已,作用是把第一个元素作为 memo 值。
接着就是有没有初始化都共用的部分了,通过一个 for 循环把 keys 遍历,并把相应的信息交给 iteratee 去处理,参数 memo 是上一次处理结果。遍历完后把最后的处理结果 memo 返回就完了。
这个函数派生了两个方法,即

_.reduce = _.foldl = _.inject = createReduce(1);
_.reduceRight = _.foldr = createReduce(-1);

只是方向不同而已。
举个例子方便理解些,例如:

var sum = _.reduce([1, 2, 3, 4, 5], function(accumulator, value, index, collection) {
  return accmulator + value;
}, 0);

结果为 15 这个应该很明显,js 原生也有 reduce 方法,如下:

[1, 2, 3, 4, 5].reduce(function(left, right) {
  return left + right;
});

我们看下 Underscore 的例子,主要想说明下他的运行过程,如下:

if(!initial)
    memo = 1; index = 1;
endif
for
    memo = iteratee(1, 2, 1, [1, 2, 3, 4, 5]) = 3;
    memo = iteratee(3, 3, 2, [1, 2, 3, 4, 5]) = 6;
    memo = iteratee(6, 4, 3, [1, 2, 3, 4, 5]) = 10;
    memo = iteratee(10, 5, 4, [1, 2, 3, 4, 5]) = 15;
endfor
return memo = 15;

额,我也不知道写的是什么东西,只是描述下过程而已,你懂的。
剩下的集合部分感觉也没啥好说的了,花点时间看下就可以看懂了=.=。