源码学习——lodash(二)

619 阅读3分钟

前言

上节我们介绍了lodash三个方法的源码,本节我们继续来看数组相关方法。

difference

difference可以将两个数组进行对比,返回一个过滤掉特定值的新数组。它有两个参数,一个为检查数组,一个为排除数组。

   _.difference(array, [values])
   array 检查数组
   [values] 排除数组
   _.difference([1,2],[2,3]) //[1]

该方法有点像filter的升级版,具体的源码如下:

QQ图片20240222234404.png
源码非常的简单,就是一个三目运算,下面我们就解析一下里面的方法:

  1. isArrayLikeObject检查参数是否为数组,该方法是lodash基础方法,源码写的比较分散,这里我合并了一下方便查阅。 QQ图片20240225194330.png
    判断思路很简单,先判断是否为Object,然后判断是否为数组,都是用type of就行了简单判断,其中数组的判断加上了isLength,该方法就是校验是否正整数并加上了长度校验。数组校验方法有很多,一般我们直接用isArray就判断了,之所以lodash不用,猜想还是想坚持避免使用数组方法。
  2. baseDifference核心方法,返回result。这里传了两个参数,其中第二个参数用baseFlatten将排除数组进行了扁平化的处理。baseDifference总共有四个参数,iteratee与comparator是后两个方法相关,源码逻辑是先进行了判断处理:

QQ图片20240225200103.png
对于baseDifference我们直接看后面的源码:

QQ图片20240225201431.png

  • 用for of循环检查数组array,接着进入判断,isCommon就是baseDifference逻辑。
  • 用while循环排除数组values,当排除数组的值等于当前元素时,就用continue跳过此次循环,不等就添加到result中。这里注意一下判断有一个computed === computed,computed是处理过后的元素,为什么会判断严格相等一下呢?其实这里就是为了判断一些特殊类型比如NaN,细节拉满。

differenceBy

differenceBy是在difference的基础上加上了iteratee迭代器,数组中的元素会先经过迭代器处理,然后再进行比较,比如对象数组,我们可以指定比较的key。

_.differenceBy([{id:1,{id:2}],[{id:1}],'x') //[{id:2}]

该方法源码就是在difference基础上加了对迭代器的判断,核心方法还是baseDifference。

QQ图片20240225225819.png
回到上面baseDifference源码中,当存在iteratee时,会利用map方法对元素进行处理,values会在循环前进行处理,而array的值是在循环中进行处理的,后面逻辑都是一样的。

differenceWith

differenceWith是加上了comparator比较器参数,comparator有两个参数,一个是array的值,一个是values的值,comparator会调用每个值按照比较条件将数据进行过滤。

// 去掉相等的
_.differenceWith([1,2],[1],_.isEqual) //[2]

QQ图片20240225231626.png 很简单,我们还是继续研究baseDifference,comparator逻辑相对复杂点,先定义了isCommon将其与difference区分开,然后采用includes方法进行比较判断,comparator对应的includes是arrayIncludesWith

QQ图片20240225235242.png
通过for of循环array元素,与目标target执行comparator比较器,这就是isCommon对应else if的内容,条件不成立的就会被添加到result。

总结

上述三个方法都是在baseDifference基础上进行实现的,所以baseDifference方法考虑得很周全。三种方法都是比较过滤两个数组的,我们碰到合适的需求可以用这三种方法。