源码学习——lodash(五)

225 阅读3分钟

前言

平时大家面试的时候可能遇到过数组扁平化,再狠一点的手写扁平化,本节我们就来介绍一下lodash扁平化相关的方法,拿捏数组扁平化。

flatten

flatten将嵌套数组减少一层级,简单来说就是可以把二维数组变成一维数组。

_.flatten(array)
_.flatten([[1]]) //[1]

注意如果元素本身没有嵌套就不会受影响,flatten源码很简单:

image.png
简单判断下数组,然后就是核心方法baseFlatten,该方法后面一起解析。

flattenDeep

flattenDeep将嵌套数组变为一维数组,不管元素嵌套了多少层,最终都能够处理为一维。

_.flattenDeep(array)
_.flattenDeep([[1,[2]]]) //[1,2]

image.png
对比flatten,Deep就是baseFlatten第二个参数变成了INFINITY,而INFINITY等于1/0,表示无穷大。根据js的运算准则,当被除数为0时结果就是Infinity。 image.png

flattenDepth

flateenDepth可以将嵌套数组减少n个层级,该方法接收两个参数,array和depth(减少的层级,默认为1),很明显flattenDep不传参数时效果就跟flatten一样,当depth层级是嵌套的最多层级效果就跟flattenDeep一样。

_.flattenDepth(array,depth)
_.flattenDepth([[1,[2]]]) //[1,[2]]

QQ图片20240326225325.png
增加了对depth的判断,然后将depth当做baseFlateen第二个参数。接下来我们就来解析一下核心方法baseFlateen

baseFlatten

找到baseFlateen.ts文件,查看具体的源码: Q5$$4ZQP0P2CGK22{7KIA.png
该方法总共有5个参数,而以上三个方法只用到了前两个参数,剩余参数分别为:

  • predicate:表示迭代函数,默认值为isFlattenable函数,该函数对value值进行检查并返回布尔值。 QQ图片20240326231751.png
    该方法用三个或连接,其中spreadableSymbol,它等于Symbol.isConcatSpreadable,该符号是个布尔值,在数组用concat方法时,如果将连接数组该符号设置为fale,连接数组将不会进行展开。
const a = [1];
const b = [2];
console.log(a.concat(b)); // [1,2]
b[Symbol.isConcatSpreadable] = false;
console.log(a.concat(b)); // [1,[2]]
  • isStrict:布尔值,为true时,只保留通过predicate函数检查的值,默认为空,在判断时候取反,也就是会把数组中的原元素都会被保留。
  • result:表示初始结果数组,默认为空数组,处理过后的数据,会添加到result里面,最后返回。 了解全部的参数,源码解读也就变得很简单了。
  1. 首先用||进行非空判断,接着用for of循环数组
  2. 如果depth大于0并且处理过后的value是数组或者嵌套数组的,就进入下一步;否则根据isStrict参数进行判断,将value从后面添加。
  3. 判断depth,如果大于1就进行迭代,否则通过扩展运算符将其添加到result里面。这一步是核心步骤,总结下来就是迭代+扩展运算符。扩展运算符会调用数组原型中的迭代器循环元素,具体的原理大家感兴趣的也可以去了解。

总结

flatten相关方法利用迭代加扩展运算符得到结果,只要记住这两个关键步骤,在面试中碰到扁平问题我们就可以从这两方面回答。