源码阅读经验
lodash
的代码分为两大块: 一个是.internal
目录里的文件,这些是lodash
内部使用的『基础函数』,不会暴露在全局的lodash
对象上;其他的文件都在根目录下,每个函数对应一个文件,这些都会挂在lodash/_
下,我习惯称为『外部函数』。
『外部函数』通常会依赖一些『基础函数』,而『基础函数』很少有依赖,自成一统。lodash
通过这种方式最大化使代码复用。
[TOC]
Array
整理了一下Array
类别下『外部函数』与『基础函数』的对应关系,画个图:
lodash-array-part1
lodash-array-part2
concat
1 | _.concat([1], [2], [3, 4]); |
源码
1 | /** |
difference
示范:
1 | _.difference([2, 1], [2, 3]); // [1] |
源码
1 | function difference(array, ...values) { |
baseFlatten
1 | /** |
baseDifference
1 | /** |
dropRightWhile、dropWhile
示范
1 | var users = [{ user: 'barney', active: true }, { user: 'fred', active: false }, { user: 'pebbles', active: false }]; |
1 | var users = [{ user: 'barney', active: false }, { user: 'fred', active: false }, { user: 'pebbles', active: true }]; |
源码
1 | function dropRightWhile(array, predicate) { |
底层都是用的同一个baseWhile
函数:
1 | /** |
flattern
、flatternDeep
底层也是用的baseFlattern
函数,见difference
indexOf
1 | _.indexOf([1, 2, 1, 2], 2); |
源码
1 | function indexOf(array, value, fromIndex) { |
主要是要考虑 NaN 的情况.
1 | /** |
intersection
、intersectionBy
、intersectionWith
1 | _.intersection([2, 1], [2, 3]); |
源码
大致思路: 迭代第一个参数数组,看看每一个元素在其他参数数组中是否存在,如果都存在就放在交集中。在判断是否存在时,会根据情况使用 Set/Map 或者数组进行查找。同时第一个数组中的元素也要去重。
1 | /** |
pull、pullAll、pullAllBy、pullAllWith
1 | var array = ['a', 'b', 'c', 'a', 'b', 'c']; |
源码
底层用到了一个共同的函数basePullAll
:
1 | /** |
pullAt
1 | var array = ['a', 'b', 'c', 'd']; |
对应的核心文件是basePullAt
:
1 | /** |
sortedIndex、sortedIndexBy、sortedIndexOf、sortedLastIndex、sortedLastIndexBy、sortedLastIndexOf
- TODO
sortedUniq、sortedUniqBy
1 | _.sortedUniq([1, 1, 2]); |
源码
二者都是用到一个工具函数baseSortedUniq
:
1 | /** |
其中的eq
函数值得注意,它考虑了NaN
的情况:
1 | /** |
union、unionBy、unionWith、uniq、uniqBy、uniqWith
union 取并集、uniq 去重
1 | _.union([2], [1, 2]); |
源码
union 操作符的思路都是先将所有参数数组打平合并到一个大数组里,然后对这个大数组去重。
uniq 的参数直接就是一个大数组
1 | function union(...arrays) { |
1 | /** Used as the size to enable large array optimizations. */ |
zip、unzip
1 | var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); |
源码
1 | /** |
1 | function zip(...arrays) { |
unzipWith、zipWith
源码
1 | // 先将array进行unzip,然后针对结果集数组的每个子元素应用iteratee即可。 |
zipObjectDeep
- TODO
xor、xorBy、xorWith
1 | _.xor([2, 1], [2, 3]); |
源码
底层都是用的同一个baseXor
函数
1 | /** |