该项目的 GitHub 地址为 underscore-analysis,所有文章都在这里,并将不断更新。如果你觉得我的解读还可以,对你学习 js 有一定的帮助,欢迎 Watch && Star,你的关注和肯定必定会促使我投入更多的时间和经历做好这个系列。如果你愿意的话,也欢迎 Fork,我们一起来将这个系列做好做大,一起成长。
原生的 ES5 提供了很多关于的迭代方法,但是对于对象只能通过 for in 循环,或者用 Object.keys(obj) 提取出对象的属性后,再用数组的方法迭代这些提取出来的属性。underscore 针对这种情况定义了很多既可以迭代数组(包括类数组)也可以迭代对象的方法,这些方法被称为 Collection Functions(集合方法),这里的集合指的是可迭代的序列(数组或对象)。这篇文章起,我们将对这些方法进行一一解读。
1 _.each(list, iteratee, context)
该方法与 ES5 中的 forEach 方法类似,会遍历 list 中的所有元素,并按顺序用 iteratee 去处理每个迭代的元素,iteratee 被绑定了 context 上下文。如果 list 是一个数组,每次调用 iteratee 都会传递三个参数:(element, index, list)。如果 list 是一个对象,iteratee 的参数是:(value, key, list)。最后返回 list 以方便链式调用。
示例
源码解读
这个方法依赖了 isArrayLike 和 optimizeCb 两个内部函数,这两个内部函数在之前的文章中介绍过,有兴趣的可以看一下。
2 _.map(list, iteratee, context)
该方法与 ES5 中的 map 方法类似,会遍历 list 中的所有元素,当 iteratee 按顺序去处理每个迭代的元素时会返回一个新元素,这个新元素被加入到该方法最后返回的数组中。 也就是说,该方法会将 list 中的每个元素映射为一个新元素,并最终构成一个新的数组返回。
示例:
源码解读:
3 _.reduce(list, iteratee, memo, context)
该方法把 list 中的所有元素归结(折叠)为一个数值返回,iteratee 是迭代中使用的回调函数,memo 是折叠时的初始值,context 是回调函数的上下文。underscore 还提供了一个相似的方法 reduceRight,reduce 方法是从左开始折叠,reduceRight 是从右开始折叠。
示例:
源码解读:
这两个方法都严重依赖了一个内部函数 createReduce,我们来仔细看一下:
这个方法之所以比 each 和 map 复杂很多,是因为要考虑到折叠的方向既从那边开始迭代,所以首先要获取迭代的初始索引和折叠的初始值。