欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JS中的reduce fold unfold用法

 更新時(shí)間:2021年05月07日 10:58:48   作者:淺笑·  
這篇文章主要介紹了JS中的reduce fold unfold用法,想深入了解JS的同學(xué),一定要看下

fold(reduce)

說(shuō)說(shuō)reduce吧, 很喜歡這個(gè)函數(shù),節(jié)省了不少代碼量,而且有一些聲明式的雛形了,一些常見(jiàn)的工具函數(shù),flatten,deepCopy,mergeDeep等用reduce實(shí)現(xiàn)的很優(yōu)雅簡(jiǎn)潔。reduce也稱(chēng)為fold,本質(zhì)上就是一個(gè)折疊數(shù)組的過(guò)程,把數(shù)組中的多個(gè)值經(jīng)過(guò)運(yùn)算變成一個(gè)值,每次運(yùn)算都會(huì)有一個(gè)函數(shù)處理,這個(gè)函數(shù)就是reduce的核心元素,稱(chēng)之為reducer,reducer函數(shù)是個(gè)2元函數(shù),返回1個(gè)單值,常見(jiàn)的add函數(shù)就是reducer

const addReducer = (x, y) => x + y;

這個(gè)add函數(shù)就是一個(gè)reducer,最常見(jiàn)的用法就是結(jié)合數(shù)組的reduce方法來(lái)用

[1, 2, 3, 4, 5].reduce(addReducer, 0) // 15

為了更好的理解reduce,下面用不同的思路實(shí)現(xiàn)一遍這個(gè)函數(shù)

使用for...of

const reduce = (f, init, arr) => {
  let acc = init;
  for (const item of arr) {
    acc = f(acc, item);
  }
  return acc
}
// 執(zhí)行
reduceFor(addReducer, 0, [1, 2, 3, 4, 5])  // 15

使用while循環(huán)

reduce = (f, init, arr) => {
  let acc = init;
  let current;
  let i = 0;
  while ((current = arr[i++])) {
    acc = f(acc, current);
  }
  return acc;
}

// 執(zhí)行
reduceFor(addReducer, 0, [1, 2, 3, 4, 5])  // 15

更像fold的實(shí)現(xiàn)

上面的實(shí)現(xiàn)也都好理解,但好像沒(méi)有體現(xiàn)出來(lái)折疊(fold)這個(gè)過(guò)程,折疊應(yīng)該是對(duì)數(shù)組的層層擠壓操作,上面的實(shí)現(xiàn)數(shù)組和邏輯其實(shí)是分開(kāi)了,而且也引入了比較多的中間變量,雖然是在內(nèi)部沒(méi)有副作用吧。
其實(shí)換個(gè)思路想一下,如果把狀態(tài)通過(guò)參數(shù)來(lái)傳遞,就可以更好的體現(xiàn)fold的過(guò)程,這里的參數(shù)是值是指逐漸變化的數(shù)組和計(jì)算值,并可以盡可能的做到無(wú)狀態(tài),真正純函數(shù)的實(shí)現(xiàn)是沒(méi)有表達(dá)式,只有語(yǔ)句的,這個(gè)可以用遞歸做到。下面的實(shí)現(xiàn)是用尾遞歸實(shí)現(xiàn)的reduce,可以在實(shí)現(xiàn)的過(guò)程中就看出數(shù)組和計(jì)算值是怎樣變化的。非常符合fold這個(gè)稱(chēng)謂

function reduce(f, init, arr) {
  if (arr.length === 0) return init;
  const [head, ...rest] = arr;
  return reduceRecursion(f, f(init, head), rest);
}

// 執(zhí)行
reduceFor(addReducer, 0, [1, 2, 3, 4, 5])  // 15

unfold

fold反過(guò)來(lái)就是unfold,unfold顧名思義就是根據(jù)一個(gè)反過(guò)來(lái)的reducer,來(lái)生成一系列的值。此時(shí)這個(gè)如果說(shuō)原來(lái)的reducer實(shí)現(xiàn)類(lèi)似于(a, b) -> c,那反過(guò)來(lái)就是c -> [a, b], 生成序列是一個(gè)很基本的操作,但就是這個(gè)基本的操作,也有很多實(shí)現(xiàn)的思路,在介紹unfold之前,看一下實(shí)現(xiàn)序列的其他方法,最后來(lái)做一個(gè)對(duì)比。

序列的實(shí)現(xiàn)

range(0, 100, 5)

期待結(jié)果

[0, 5, 10, ... 95]

數(shù)組實(shí)現(xiàn)

這個(gè)就不多說(shuō)了,大家應(yīng)該都知道。

range = (first, last, step) => {
  const n = (last - first) / step + 1;
  return Array.from({ length: n - 1 })
            .map((_, index) => first + index * step);
}
// 也可以使用from的第二個(gè)參數(shù)
// Array.from({ length: n }, (_, i) => first + i * step);

生成器實(shí)現(xiàn)

生成序列還有一個(gè)利器,那就是generator,生成器生成器,就是用來(lái)生成數(shù)據(jù)的。generator返回一個(gè)迭代器,也很容易生成序列

function* range(first, last, step) {
  let acc = first;
  while (acc < last) {
    yield acc;
    acc = acc + step;
  }
}
[...range(0, 100, 5)]

兩者相比,generator更注重生成的過(guò)程,Array注重?cái)?shù)據(jù)變化的過(guò)程。

unfold實(shí)現(xiàn)

在實(shí)現(xiàn)unfold之前,首先梳理一下實(shí)現(xiàn)思路,和fold一樣,也是用遞歸,且要在實(shí)現(xiàn)的過(guò)程中看到對(duì)應(yīng)數(shù)據(jù)的變化。大體過(guò)程如下

0 -> [0, 5]

5 -> [5, 10]

10 -> [10, 15]

15 -> [15, 20]

...

90 -> [90, 95]

95 -> [95, 100]

可以看出過(guò)程恰恰是fold反過(guò)來(lái),符合c -> [a, b]因?yàn)槌跏贾悼隙橐粋€(gè)數(shù)組,所以u(píng)nfold只需要兩個(gè)參數(shù),實(shí)現(xiàn)如下。

function unfold(f, init) {
  const g = (f, next, acc) => {
    const result = f(next);
    const [head, last] = result || [];
    console.log(last);
    return result ? g(f, last, acc.concat(head)) : acc;
  };
  return g(f, init, []);
}

range = R.curry((first, last, step) =>
  unfold(next => next < last && [next, next + step], 0)
)

// 執(zhí)行
range(0, 100, 5)

總結(jié)

以上就是結(jié)合reduce和一個(gè)生成序列的例子簡(jiǎn)單介紹了一下fold和unfold這兩個(gè)在fp編程中很重要的概念,當(dāng)然他們功能不只是生成序列,還有很多很強(qiáng)大的功能

以上就是詳解JS中的reduce fold unfold用法的詳細(xì)內(nèi)容,更多關(guān)于JS的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • js實(shí)現(xiàn)對(duì)table動(dòng)態(tài)添加、刪除和更新的方法

    js實(shí)現(xiàn)對(duì)table動(dòng)態(tài)添加、刪除和更新的方法

    這篇文章主要介紹了js實(shí)現(xiàn)對(duì)table動(dòng)態(tài)添加、刪除和更新的方法,涉及javascript針對(duì)html中table表格節(jié)點(diǎn)的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • 使用JavaScript保存文本文件到本地的兩種方法

    使用JavaScript保存文本文件到本地的兩種方法

    今天小編就為大家分享一篇關(guān)于使用JavaScript保存文本文件到本地的兩種方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • 解決layui頁(yè)面按鈕點(diǎn)擊無(wú)反應(yīng),也不報(bào)錯(cuò)的問(wèn)題

    解決layui頁(yè)面按鈕點(diǎn)擊無(wú)反應(yīng),也不報(bào)錯(cuò)的問(wèn)題

    今天小編就為大家分享一篇解決layui頁(yè)面按鈕點(diǎn)擊無(wú)反應(yīng),也不報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-09-09
  • JavaScript?中創(chuàng)建私有成員

    JavaScript?中創(chuàng)建私有成員

    這篇文章主要介紹了JavaScript?中創(chuàng)建私有成員,下面介紹以?#?作為前綴幾種在?JavaScript?代碼中實(shí)現(xiàn)私有屬性和方法的方式,需要的小伙伴可以參考一下
    2021-12-12
  • JavaScript數(shù)組去重的五種方法及其他細(xì)節(jié)和拓展

    JavaScript數(shù)組去重的五種方法及其他細(xì)節(jié)和拓展

    JavaScript數(shù)組去重這個(gè)問(wèn)題,經(jīng)常出現(xiàn)在面試題中,下面這篇文章主要給大家介紹了關(guān)于JavaScript數(shù)組去重的五種方法及其他細(xì)節(jié)和拓展的相關(guān)資料,文中通過(guò)實(shí)例代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • JS搜狐面試題分析

    JS搜狐面試題分析

    這篇文章主要介紹了JS搜狐面試題,涉及javascript數(shù)組、字符串及面向?qū)ο蟪绦蛟O(shè)計(jì)相關(guān)技巧,需要的朋友可以參考下
    2016-12-12
  • 光標(biāo)的一些操作總結(jié)

    光標(biāo)的一些操作總結(jié)

    IE下的Range操作比Mozilla下強(qiáng)很多,這里只討論IE下的操作,這里選介紹幾個(gè)光標(biāo)定位的特點(diǎn)
    2006-10-10
  • JS運(yùn)動(dòng)特效之完美運(yùn)動(dòng)框架實(shí)例分析

    JS運(yùn)動(dòng)特效之完美運(yùn)動(dòng)框架實(shí)例分析

    這篇文章主要介紹了JS運(yùn)動(dòng)特效之完美運(yùn)動(dòng)框架,結(jié)合實(shí)例形式分析了javascript針對(duì)運(yùn)動(dòng)中的元素屬性檢測(cè)與判斷相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Javascript節(jié)點(diǎn)關(guān)系實(shí)例分析

    Javascript節(jié)點(diǎn)關(guān)系實(shí)例分析

    這篇文章主要介紹了Javascript節(jié)點(diǎn)關(guān)系,實(shí)例分析了javascript操作父子節(jié)點(diǎn)及兄弟節(jié)點(diǎn)的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • 在組件外(.js文件)中使用pinia的解決方法

    在組件外(.js文件)中使用pinia的解決方法

    這篇文章主要給大家介紹了關(guān)于在組件外(.js文件)中使用pinia的解決方法, pinia是Vue的最新一代的輕量級(jí)狀態(tài)管理插件,它允許跨組件/頁(yè)面共享狀態(tài),需要的朋友可以參考下
    2024-06-06

最新評(píng)論