lodash.js源碼-flatten

功能

調用方式數組

_.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
}

lodash源碼實現

function flatten(array) {
  var length = array == null ? 0 : array.length;
  return length ? baseFlatten(array, 1) : [];
}

經過源碼,咱們能夠很清晰的獲得flatten方法的核心功能都是由baseFlatten實現的。開發

常用lodash的開發者會發現,flattenDeepflattenDepth中有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

探祕baseFlatten

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衍生出來的。

再實際開發中,咱們也要學習做者的思路去抽象封裝代碼。

相關文章
相關標籤/搜索