<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【JavaScript】以前我沒得選,現(xiàn)在我只想用 Array.prototype.reduce

          共 8397字,需瀏覽 17分鐘

           ·

          2021-05-09 02:46

          前言

          對于新手來說, reduce 沒有 map、 forEach、 filter 等數(shù)組方法那么友好。但是不得不說,它們能干的事情, reduce 一個不落下,直呼“B神”。

          我心目中 reduce 的形象。

          寫這篇文章的目的就是想給大家好好的介紹一下 reduce 它有多“騷”。

          語法

          reduce 接收 2 個參數(shù):第一個參數(shù)是回調函數(shù)(必選),第二個參數(shù)是初始值 initialValue(可選) 。而第一個參數(shù)(回調函數(shù)),接收下面四個參數(shù):

          • Accumulator (acc) (累計器)
          • Current Value (cur) (當前值)
          • Current Index (idx) (當前索引)
          • Source Array (src) (源數(shù)組)

          我們平時在業(yè)務中多數(shù)使用到的是前兩個參數(shù),并且有以下兩種情況。

          瀏覽器支持情況

          圖片來源:caniuse.com/

          不帶初始值

          [1,2,3,4].reduce((acc, cur) => {
            return acc + cur
          })
          // 1 + 2 + 3 + 4
          // 10

          帶初始值

          [1,2,3,4].reduce((acc, cur) => {
            return acc + cur
          }, 10)
          // 10 + 1 + 2 + 3 + 4
          // 20

          ?? 初始值 initialValue 可以是任意類型。如果沒有提供 initialValuereduce 會從索引 1 的地方開始執(zhí)行 callback 方法,跳過第一個索引。如果提供 initialValue,從索引 0 開始。它的執(zhí)行就像一個貪吃蛇,蛇每吃一個豆子,豆子將會變成蛇身的一部分,蛇再去吃下一個豆子。 

          重塑

          它的能力遠不止于此,它就像神奇寶貝里的“百變怪”,想要變成什么就變成什么。 

          reduce -> map

          map 方法接收一個回調函數(shù),函數(shù)內接收三個參數(shù),當前項、索引、原數(shù)組,返回一個新的數(shù)組,并且數(shù)組長度不變。知道了這些特征之后,我們用 reduce 重塑 map 。

          const testArr = [1234]
          Array.prototype.reduceMap = function(callback{
            return this.reduce((acc, cur, index, array) => {
              const item = callback(cur, index, array)
              acc.push(item)
              return acc
            }, [])
          }
          testArr.reduceMap((item, index) => {
            return item + index
          })
          // [1, 3, 5, 7]

          在 Array 的原型鏈上添加 reduceMap 方法,接收一個回調函數(shù) callback 作為參數(shù)(就是 map 傳入的回調函數(shù)),內部通過 this 拿到當前需要操作的數(shù)組,這里 reduce 方法的第二個參數(shù)初始值很關鍵,需要設置成一個 [] ,這樣便于后面把操作完的單項塞入 acc 。我們需要給 callback 方法傳入三個值,當前項、索引、原數(shù)組,也就是原生 map 回調函數(shù)能拿到的值。返回 item 塞進 acc,并且返回 acc ,作為下一個循環(huán)的 acc(貪吃蛇原理)。最終 this.reduce 返回了新的數(shù)組,并且長度不變。

          reduce -> forEach

          forEach 接收一個回調函數(shù)作為參數(shù),函數(shù)內接收四個參數(shù)當前項、索引、原函數(shù)、當執(zhí)行回調函數(shù) callback 時,用作 this 的值,并且不返回值。

          const testArr = [1234]
          Array.prototype.reduceForEach = function(callback{
            this.reduce((acc, cur, index, array) => {
              callback(cur, index, array)
            }, [])
          }

          testArr.reduceForEach((item, index, array) => {
            console.log(item, index)
          })
          // 1234
          // 0123

          只要看得懂 reduce -> map ,轉 forEach 只是改改結構的問題。

          reduce -> filter

          filter 同樣接收一個回調函數(shù),回調函數(shù)返回 true 則返回當前項,反之則不返回?;卣{函數(shù)接收的參數(shù)同 forEach 。

          const testArr = [1234]
          Array.prototype.reduceFilter = function (callback{
             return this.reduce((acc, cur, index, array) => {
              if (callback(cur, index, array)) {
                acc.push(cur)
              }
              return acc
            }, [])
          }
          testArr.reduceFilter(item => item % 2 == 0// 過濾出偶數(shù)項。
          // [2, 4]

          filter 方法中 callback 返回的是 Boolean 類型,所以通過 if 判斷是否要塞入累計器 acc ,并且返回 acc 給下一次對比。最終返回整個過濾后的數(shù)組。

          reduce -> find

          find 方法中 callback 同樣也是返回 Boolean 類型,返回你要找的第一個符合要求的項。

          const testArr = [1234]
          const testObj = [{ a1 }, { a2 }, { a3 }, { a4 }]
          Array.prototype.reduceFind = function (callback{
            return this.reduce((acc, cur, index, array) => {
              if (callback(cur, index, array)) {
                if (acc instanceof Array && acc.length == 0) {
                 acc = cur
                }
              }
              // 循環(huán)到最后若 acc 還是數(shù)組,且長度為 0,代表沒有找到想要的項,則 acc = undefined
              if ((index == array.length - 1) && acc instanceof Array && acc.length == 0) {
                acc = undefined
              }
              return acc
            }, [])
          }
          testArr.reduceFind(item => item % 2 == 0// 2
          testObj.reduceFind(item => item.a % 2 == 0// {a: 2}
          testObj.reduceFind(item => item.a % 9 == 0// undefined

          你不知道操作的數(shù)組是對象數(shù)組還是普通數(shù)組,所以這里只能直接覆蓋 acc 的值,找到第一個符合判斷標準的值就不再進行賦值操作。

          諸如此類的操作,大家可以自己練習,就當是再熟悉一遍 Array 數(shù)組方法。

          衍生

          同學們可能在業(yè)務中,對 reduce 使用頻率并不高,那是因為你沒有很好的去理解它。在很多業(yè)務場景下,你用了更麻煩、更冗余的代碼完成了你的需求。接下帶大家學習一些用 reduce 能解決的問題。

          將二維數(shù)組轉為一維數(shù)組

          const testArr = [[1,2], [3,4], [5,6]]
          testArr.reduce((acc, cur) => {
            return acc.concat(cur)
          }, [])
          // [1,2,3,4,5,6]

          計算數(shù)組中每個元素出現(xiàn)的個數(shù)

          const testArr = [1341329853201210]
          testArr.reduce((acc, cur) => {
            if (!(cur in acc)) {
              acc[cur] = 1
            } else {
              acc[cur] += 1
            }
            return acc
          }, {})

          // {0: 1, 1: 2, 2: 2, 3: 3, 4: 1, 5: 1, 8: 1, 9: 1, 10: 1, 12: 1}

          這里注意,我初始化的值變成了 {} ,這個需求需要鍵值對的形式,利用 cur in acc 判斷累計器 acc 中是否含有 cur 屬性,如果沒有默認賦值 1,如果已經(jīng)存在 += 1 累加一次。在實際的開發(fā)業(yè)務中,這個方法非常常用,變種也很多。比如給你一個賬單列表(項與項之間的消費類型有相同情況),讓你統(tǒng)計賬單列表中各個消費類型的支出情況,如 購物 、 學習 、 轉賬 等消費類型的支出情況。這就用到了上述方法,去通過歸類。

          按屬性給數(shù)組分類

          什么叫按照屬性給數(shù)組分類,其實就是給定一個依據(jù),把符合條件的歸并到一起。再拿賬單舉例,就是按各個消費類型歸為一類。

          const bills = [
            { type'shop'momey223 },
            { type'study'momey341 },
            { type'shop'momey821 },
            { type'transfer'momey821 },
            { type'study'momey821 }
          ];
          bills.reduce((acc, cur) => {
            // 如果不存在這個鍵,則設置它賦值 [] 空數(shù)組
            if (!acc[cur.type]) {
              acc[cur.type] = [];
            }
            acc[cur.type].push(cur)
            return acc
          }, {})

          數(shù)組去重

          這個就不解釋了,直接上代碼。

          const testArr = [1,2,2,3,4,4,5,5,5,6,7]
          testArr.reduce((acc, cur) => {
            if (!(acc.includes(cur))) {
              acc.push(cur)
            }
            return acc
          }, [])
          // [1, 2, 3, 4, 5, 6, 7]

          上述代碼邏輯,就是逐一對比,通過 includes 方法檢查累計器里是否已經(jīng)有當前項。

          求最大值或最小值

          一個對象數(shù)組內,我想拿到某一項里某個屬性最大或者最小的那一項。

          const testArr = [
            { age20 },
            { age21 },
            { age22 }
          ]
          testArr.reduce((acc, cur) => {
            if (!acc) {
              acc = cur
              return acc
            }
            if (acc.age < cur.age) {
              acc = cur
              return acc
            }
            return acc
          }, 0)
          // {age: 22}

          第一次沒有對比直接 acc 賦值 cur ,后面進入對比判斷,如果 acc 的 age 屬性小于 cur 的 age 屬性,重制 acc 。相等的話默認返回 acc 。

          總結

          reduce 的使用場景還有非常多,當你遇到數(shù)組復雜操作的時候,就是它大顯身手的時候。深入研究它,對你今后的業(yè)務開發(fā)及面試都有很大的幫助。



          瀏覽 45
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中国一级黄色毛片 | 99热在线免费 | 九九在线精品 | 五月丁香婷婷激情综合 | 午夜色色色色 |