<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>

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

          共 8418字,需瀏覽 17分鐘

           ·

          2021-03-25 12:54

          前言

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

          我心目中 reduce 的形象。

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

          語法

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

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

          我們平時在業(yè)務(wù)中多數(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 可以是任意類型。如果沒有提供 initialValue,reduce 會從索引 1 的地方開始執(zhí)行 callback 方法,跳過第一個索引。如果提供 initialValue,從索引 0 開始。它的執(zhí)行就像一個貪吃蛇,蛇每吃一個豆子,豆子將會變成蛇身的一部分,蛇再去吃下一個豆子。 

          重塑

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

          reduce -> map

          map 方法接收一個回調(diào)函數(shù),函數(shù)內(nèi)接收三個參數(shù),當(dāng)前項(xiàng)、索引、原數(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 方法,接收一個回調(diào)函數(shù) callback 作為參數(shù)(就是 map 傳入的回調(diào)函數(shù)),內(nèi)部通過 this 拿到當(dāng)前需要操作的數(shù)組,這里 reduce 方法的第二個參數(shù)初始值很關(guān)鍵,需要設(shè)置成一個 [] ,這樣便于后面把操作完的單項(xiàng)塞入 acc 。我們需要給 callback 方法傳入三個值,當(dāng)前項(xiàng)、索引、原數(shù)組,也就是原生 map 回調(diào)函數(shù)能拿到的值。返回 item 塞進(jìn) acc,并且返回 acc ,作為下一個循環(huán)的 acc(貪吃蛇原理)。最終 this.reduce 返回了新的數(shù)組,并且長度不變。

          reduce -> forEach

          forEach 接收一個回調(diào)函數(shù)作為參數(shù),函數(shù)內(nèi)接收四個參數(shù)當(dāng)前項(xiàng)、索引、原函數(shù)、當(dāng)執(zhí)行回調(diào)函數(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 ,轉(zhuǎn) forEach 只是改改結(jié)構(gòu)的問題。

          reduce -> filter

          filter 同樣接收一個回調(diào)函數(shù),回調(diào)函數(shù)返回 true 則返回當(dāng)前項(xiàng),反之則不返回?;卣{(diào)函數(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ù)項(xiàng)。
          // [2, 4]

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

          reduce -> find

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

          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,代表沒有找到想要的項(xiàng),則 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 的值,找到第一個符合判斷標(biāo)準(zhǔn)的值就不再進(jìn)行賦值操作。

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

          衍生

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

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

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

          計(jì)算數(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 判斷累計(jì)器 acc 中是否含有 cur 屬性,如果沒有默認(rèn)賦值 1,如果已經(jīng)存在 += 1 累加一次。在實(shí)際的開發(fā)業(yè)務(wù)中,這個方法非常常用,變種也很多。比如給你一個賬單列表(項(xiàng)與項(xiàng)之間的消費(fèi)類型有相同情況),讓你統(tǒng)計(jì)賬單列表中各個消費(fèi)類型的支出情況,如 購物 、 學(xué)習(xí) 、 轉(zhuǎn)賬 等消費(fèi)類型的支出情況。這就用到了上述方法,去通過歸類。

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

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

          const bills = [
            { type'shop'momey223 },
            { type'study'momey341 },
            { type'shop'momey821 },
            { type'transfer'momey821 },
            { type'study'momey821 }
          ];
          bills.reduce((acc, cur) => {
            // 如果不存在這個鍵,則設(shè)置它賦值 [] 空數(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ì)器里是否已經(jīng)有當(dāng)前項(xiàng)。

          求最大值或最小值

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

          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 ,后面進(jìn)入對比判斷,如果 acc 的 age 屬性小于 cur 的 age 屬性,重制 acc 。相等的話默認(rèn)返回 acc 。

          總結(jié)

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

           點(diǎn)擊閱讀原文,快來加入我們吧!

          瀏覽 49
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  日韩无码专区电影 | 无码a√中文字幕 | 经典三级精品国产 | 国产五月丁香好好日 | 超碰97在线播放 |