中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

reduce lodash.reduce實現原理是什么

發布時間:2023-02-27 09:37:07 來源:億速云 閱讀:109 作者:iii 欄目:開發技術

本篇內容主要講解“reduce lodash.reduce實現原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“reduce lodash.reduce實現原理是什么”吧!

基本實現

實現思路:

  • 判斷是否有初始值,因為有初始值和沒有初始值對回調函數(reducer)執行的次數是有影響的。

  • 遍歷數組

  • 組合參數傳遞給 reducer 進行執行

  • 獲取到第三步返回值的時候,要把返回值存儲起來,在下一次便利的時候作為reducer第一個參數來替換初始值。

  • 返回最終計算的value值

function reduce(array, reducer, initialValue = null) {
    let value = initialValue === null ? array[0] : initialValue; // 思路1
    let startIndex = initialValue === null ? 1 : 0; // 思路1
    for(let i = startIndex; i < array.length; i++) { // 思路 2
        const item = array[i]
        const res = reducer(value, item, i) // 思路3
        value = res; // 思路4
    }
    return value; // 思路5
}

測試一下:

console.log(reduce([1,2,3], (a, b) => (a + b), 0)) // 6
console.log(reduce([1,2,3], (a, b) => (a + b))) // 6

看起來是不是挺簡單的,代碼其實還可以更簡潔一點:

function reduce(array, reducer, value = null) {
    value = value === null ? array[0] : value;
    for(let i = null ? 1 : 0; i < array.length; i++) {
        value = reducer(value, array[i], i);
    }
    return value;
}

lodash 中的 reduce 實現有何不同?

lodash中 的 reduce 不僅可以對數組生效,也可以對普通 object 、類數組對象生效。

不過也針對數組其實單獨實現了一個 arrayReduce 函數,不過沒有對外。

來看一下 reducearrayReduce 源碼

function reduce(collection, iteratee, accumulator) {
  const func = Array.isArray(collection) ? arrayReduce : baseReduce
  const initAccum = arguments.length < 3
  return func(collection, iteratee, accumulator, initAccum, baseEach)
}

function arrayReduce(array, iteratee, accumulator, initAccum) {
  let index = -1
  const length = array == null ? 0 : array.length

  if (initAccum && length) {
    accumulator = array[++index]
  }
  while (++index < length) {
    accumulator = iteratee(accumulator, array[index], index, array)
  }
  return accumulator
}

看得懂嗎?不理解的話看下面一份代碼,我把非數組類型的代碼去掉,再調一下變量命名和新增注釋:

function reduce(array, reducer, value) {
  const noInitialValue = arguments.length < 3 // 用參數的數量來判斷是否有初始值
  
  let index = -1 // 遍歷索引 - 1,因為下面 while 循環前先加了 1
  const length = array == null ? 0 : array.length // 判斷數組是否存在和緩存數組長度
  // 這個if 語句中做了我上面思路1中初始值的問題和遍歷次數的問題
  if (noInitialValue && length) { // && length 判斷了數組是否為空
    value = array[++index] // 沒有有初始值,則取數組中第一為,注意 index 變成了0,下面 while 循環前會先加 1,因此循環次數會少一次。
  }
  while (++index < length) {
    value = reducer(value, array[index], index, array)
  }
  return value
}

可以看出其實大部分邏輯還是和前面的簡單實現差不多,不過考慮更全一些,有值得借鑒的地方:

  • 參數判斷邏輯更有力,不管外界傳遞了第三個參數是啥,都說明有初始值

  • 考慮了數組不存在或者為空的情況

下面我們再看一下,去除數組相關的代碼來看看針對其他對象類型怎么處理的。

function reduce(collection, iteratee, accumulator) {
  const func = baseReduce;
  const initAccum = arguments.length < 3
  return func(collection, iteratee, accumulator, initAccum, baseEach)
}

其他類型的都會教給 baseReduce 函數去處理。

// baseReduce
function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
  // 使用外部傳遞進來的遍歷方法進行遍歷對象,然后傳遞了一個 callback 給 eachFunc
  eachFunc(collection, (value, index, collection) => {
    // 初始值設置,
    accumulator = initAccum
      ? (initAccum = false, value)
      : iteratee(accumulator, value, index, collection)
  })
  return accumulator
}

使用外部傳遞進來的遍歷方法進行遍歷對象,然后傳遞了一個 callback 給 eachFunc,來執行 iteratee (也就是前面說的reducer),callback 內部的代碼就和前面 for 循環或者 while 循環的代碼類似的,就是組合參數傳遞給 reducer 進行執行,不過直接看可能有點不好理解中,了解了原理再來看應該可以理解,注意事項:

  • initAccum 為 false 時,說明有初始值,直接執行 iteratee。

  • initAccum 為 true,說明沒有初始值,需要添加初始值,因此第一次循環就是賦值給初始值,然后把 initAccum 設置為false,沒有進行執行 iteratee,比沒有初始值少一次執行,符合邏輯。

eachFunc 用的是 reduce 中傳遞進來的 baseEach,內部主要就是對對象屬性進行遍歷的操作,然后把屬性值和索引以及對象本身傳遞給 callback,稍微需要注意的就是可能遇到類數組的對象,為了保證順序,使用類數組放入索引進行遍歷,而其他對象并不能保證屬性的傳遞順序,可以再看一下baseEach實現的代碼:

function baseEach(collection, iteratee) {
  if (collection == null) {
    return collection
  }
  // 不是類數組則使用 baseForOwn 處理
  if (!isArrayLike(collection)) {
    return baseForOwn(collection, iteratee)
  }
  const length = collection.length
  const iterable = Object(collection) // 使用arguments測試了一下,好像沒啥作用
  let index = -1

  // 遍歷類數組
  while (++index < length) {
    if (iteratee(iterable[index], index, iterable) === false) {
      break
    }
  }
  return collection
}

不是 isArrayLike 的對象遍歷與本篇文章的內容沒有啥關系了,因此就不深入了。

到此,相信大家對“reduce lodash.reduce實現原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东海县| 海原县| 江孜县| 马鞍山市| 寻乌县| 抚松县| 乌鲁木齐县| 沽源县| 饶平县| 金山区| 南充市| 江源县| 冷水江市| 视频| 庆云县| 惠水县| 霍林郭勒市| 广安市| 巩留县| 五寨县| 石家庄市| 儋州市| 红桥区| 台州市| 增城市| 惠东县| 济宁市| 都兰县| 马关县| 鹤峰县| 土默特左旗| 呼玛县| 玛曲县| 奉节县| 义乌市| 沙田区| 嘉禾县| 衡水市| 武鸣县| 靖边县| 阿拉善右旗|