js之reduce巧用

在JavaScript數組函數中有一個reduce函數,和filter、map、forEach等方法略有不同,雖然中間也是有內部循環,但reduce多了一層遞歸。先看看reduce函數接收的參數。

reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;

函數規範中,第一個參數是一個回調、第二個參數是一個初始值,先來看看回調。

  • callbackfn:一個回調函數,有四個回調參數分別是:上一個返回值,當前值,當前索引、操作數組。
    後面是哪個很好理解,與filter、map等方法完全一樣,但就第一個參數——上一個返回值,這是什麼?這裏就是reduce獨特之處,這個回調參數就是遞歸出來返回的結果,reduce沒遍歷一次數組,便將返回值當做回調函數的第一個參數在此輸出(previousValue)。
    所以此處就特別注意:長度爲0的數組是不能調用reduce函數的,因爲reduce會默認遍歷+遞歸一次,意味着必須用到previousValuecurrentValue兩個參數
  • initialValue:初始值
    當沒有傳遞初始值時,reduce函數會自動遍歷+遞歸一遍,previousValue回調參數爲數組的第一個值,currentValue這個回調參數也會從數組的第二個值開始讀取。若傳遞了初始值,previousValue爲傳遞的默認值currentValue也會從數字的第1個值開始讀取。

下面我簡單的寫了一個基於reduce處理數組的工具類。包含查重、計數、求和、降維操作。

class ArrUtils {
  constructor(arr = []) {
    this.arr = arr
  }
  // 數組求和
  sum(arr = this.arr) {
    return arr.reduce((previousValue, currentValue) => previousValue + currentValue)
  }
  // 數組中對象求和 key -> 對象中的鍵名稱
  sumOfObject(key, arr = this.arr) {
    return arr.reduce((previousValue, currentValue) => previousValue + currentValue[key], 0)
  }
  // 統計
  count(arr = this.arr) {
    return arr.reduce((previousValue, currentValue) => {
      previousValue[currentValue] = currentValue in previousValue ? previousValue[currentValue] + 1 : 1
      return previousValue
    }, {})
  }
  // 查重
  checkRepeat(arr = this.arr) {
    return arr.reduce((previousValue, currentValue) => {
      return !previousValue.includes(currentValue) ? previousValue.concat(currentValue) : previousValue
    }, [])
  }
  // 扁平化
  flat(arr = this.arr) {
    return arr.reduce((previousValue, currentValue) => {
      return previousValue.concat(Array.isArray(currentValue) ? this.flat(currentValue) : currentValue)
    }, [])
  }
}

let objArr = [
  { v: 1 },
  { v: 2 },
  { v: 5 }
]
const arrUtils = new ArrUtils(objArr)
console.log(arrUtils.sumOfObject('v')) // 8

就目前來看使用reduce的場景還是比較多的,尤其是在降維方面,代碼簡潔,執行率高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章