調用方式數組
_.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
衍生出來的。
再實際開發中,咱們也要學習做者的思路去抽象封裝代碼。