调用方式数组
_.flatten(array)
减小一级array嵌套深度学习
_.flatten([1,[2,3,]]) // =< [1,2,3]
数组内的成员若是是数组,那么就会被展开到,内部的元素成为上一级数组的元素。code
这种的功能实现起来很简单,首先入参是一个数组,返回也是一个数组递归
function flatten(array){ let result = [] for(let i = 0; i< array.length; i++){ if(Array.isArray(array[i])) { // 处理数组中的元素 ,push到result中 }else { result.push(array[i]) } } return result }
function flatten(array) { var length = array == null ? 0 : array.length; return length ? baseFlatten(array, 1) : []; }
经过源码,咱们能够很清晰的获得flatten
方法的核心功能都是由baseFlatten
实现的。开发
常用lodash
的开发者会发现,flattenDeep
和flattenDepth
中有baseFlatten
源码
function flattenDepth(array, depth) { const length = array == null ? 0 : array.length if (!length) { return [] } depth = depth === undefined ? 1 : +depth return baseFlatten(array, depth) }
function flattenDeep(array) { const length = array == null ? 0 : array.length return length ? baseFlatten(array, INFINITY) : [] }
baseFlatten
正是flatten**
方法的核心实现。it
function baseFlatten(array, depth, predicate, isStrict, result) { // predicate默认为isFlattenable, 传入的array若是是能够`flatten`化,返回true, predicate || (predicate = isFlattenable) result || (result = []) if (array == null) { return result } for (const value of array) { if (depth > 0 && predicate(value)) { if (depth > 1) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, depth - 1, predicate, isStrict, result) } else { result.push(...value) } } else if (!isStrict) { result[result.length] = value } } return result }
predicate
默认为isFlattenable
, 传入的array若是是能够flatten
化,返回true
.io
假定入参baseFlatten(array, 1)
。function
接下来看具体的处理部分.抽离出代码class
for (const value of array) { if (depth > 0 && predicate(value)) { if (depth > 1) { baseFlatten(value, depth - 1, predicate, isStrict, result) } else { result.push(...value) } } else if (!isStrict) { result[result.length] = value } }
第一个判断条件
depth > 0 && predicate(value)
对flatten
来说,depth = 1
,当for...of
迭代出的元素predicate(value)
为true。
看一下默认的实现
function isFlattenable(value) { return Array.isArray(value) || isArguments(value) || !!(value && value[spreadableSymbol]) }
lodash
默认认为数组,arguments 和 value[spreadableSymbol]
是Flattenable
的。
predicate
也能够手动传入。
若是第一轮的遍历出的元素是一个数组。执行的是以下的代码。没什么好说的。
result.push(...value)
当迭代出的不是Flattenable
(或者说是predicate(value)
为false),会执行以下代码
result[result.length] = value
接下来思考depth为2的时候是下边的逻辑是如何执行的。
假设此时的入参数遍历出来的value为 ['a','b','c'].此时
if (depth > 1) { baseFlatten(value, depth - 1, predicate, isStrict, result) }
执行的就是baseFlatten(['a','b','c'],1,isFlattenable,undefined,[])
.
实际上执行的是flatten(['a','b','c'])
.只不过传入了一个result
来存放处理后的结果。depath
减小之后,就不会再向下继续执行递归了。
即使是depth
为3甚至更高的元素,也会经过递归,每一次递归的结果保存到result
中,执行到最后,即是返回最后的结果。
flatten
,flattenDeep
,flattenDepth
等方法都是经过baseFlatten
衍生出来的。
再实际开发中,咱们也要学习做者的思路去抽象封装代码。