關(guān)于 reduce 函數(shù)的思考

前言
前面的這篇文章?JS 基礎(chǔ)\! | 扁平數(shù)組和JSON樹的轉(zhuǎn)換[2]?利用到了?reduce來實(shí)現(xiàn)數(shù)組轉(zhuǎn)為map,以及結(jié)合concat實(shí)現(xiàn)數(shù)組遞歸拼接。今天我們來看看還能搞些什么名堂~
簡(jiǎn)單復(fù)習(xí)一下 reduce
語法
let?value?=?arr.reduce(function(previousValue,?item,?index,?array)?{
??//?...
},?[initial]);
復(fù)制代碼
參數(shù):
previousValue: 上一個(gè)函數(shù)調(diào)用的結(jié)果,第一次等于?initial(如果提供了?initial?的話)。item?: 當(dāng)前的數(shù)組元素。index?:當(dāng)前索引。arr?: 數(shù)組本身。
previousValue實(shí)際上有點(diǎn)像累加,所以一些地方也會(huì)叫將這個(gè)參數(shù)稱為accumulator?,存儲(chǔ)前面所有的執(zhí)行結(jié)果,最后會(huì)成為reduce的結(jié)果。
可讀性
但通常,你一般是不會(huì)完全參照這些參數(shù)定義的意思來決定參數(shù)名稱,而是要看具體開發(fā)遇到的場(chǎng)景來給其取可讀性高的名稱。
部分應(yīng)用
1. 經(jīng)典累加器
將數(shù)組中的值從左到右累加,大家學(xué)reduce的時(shí)候第一個(gè)例子應(yīng)該就是這個(gè)。這里只是簡(jiǎn)單的提一下,不是本文的重點(diǎn)~
const?a?=?[1,?2,?8,?7,?4];
const?sum?=?a.reduce((pre,?cur)?=>?{
?const?res?=?pre?+?cur;
?return?res;
},?0);
console.log(sum);?//?22
復(fù)制代碼
2. 二維數(shù)組轉(zhuǎn)一維
結(jié)合?concat?實(shí)現(xiàn)數(shù)組扁平化
const?arr2?=?[
?[1,?2],
?[3,?4],
?[5,?6],
].reduce((acc,?cur)?=>?{
?return?acc.concat(cur);
},?[]);
console.log(arr2);?//
復(fù)制代碼
3. 多維數(shù)組扁平
這個(gè)算是上一個(gè)的進(jìn)階和更為通用的版本~
這篇文章[3]里就用到了類似的,結(jié)合?concat?和遞歸
const?arr3?=?[
?[1,?2],
?[3,?4],
?[5,?[7,?[9,?10],?8],?6],
];
const?flatten?=?arr?=>
?arr.reduce(
??(pre,?cur)?=>?pre.concat(Array.isArray(cur)???flatten(cur)?:?cur),
??[]
?);
console.log(flatten(arr3));?//?[?1,?2,?3,?4,?5,?7,?9,?10,?8,?6?]
復(fù)制代碼
4. 數(shù)組分塊
根據(jù)傳入限制大小,對(duì)數(shù)組進(jìn)行分塊。
小于限制長度時(shí)就往里添加,否則直接將其加入res
const?chunk?=?(arr,?size)?=>?{
?return?arr.reduce(
??(res,?cur)?=>?(
???res[res.length?-?1].length???????res[res.length?-?1].push(cur)
????:?res.push([cur]),
???res
??),
??[[]]
?);
};
const?arr4?=?[1,?2,?3,?4,?5,?6];
console.log(chunk(arr4,?3));?//?[?[?1,?2,?3?],?[?4,?5,?6?]?]
復(fù)制代碼
5. 字符統(tǒng)計(jì)
統(tǒng)計(jì)文本中各個(gè)字的數(shù)量
const?countChar?=?text?=>?{
?text?=?text.split("");
?return?text.reduce((record,?c)?=>?{
??record[c]?=?(record[c]?||?0)?+?1;
??return?record;
?},?{});
};
const?text?=?"劃水水摸魚魚";
console.log(countChar(text));?//?{?'劃':?1,?'水':?2,?'摸':?1,?'魚':?2?}
復(fù)制代碼
思考
本文只講了幾個(gè)應(yīng)用,其實(shí)還有更多的應(yīng)用,以及一些實(shí)現(xiàn) JS API 的功能,比如
數(shù)組填充 求最大、最小值 reverse map ...
等等,這些代碼段的整合網(wǎng)上已經(jīng)有夠多了,我這里想總結(jié)一下寫出這些實(shí)用、通用的代碼需要進(jìn)行怎樣的思考
core-js
其實(shí)從?Polyfill ofArray.prototype.reduceincore-js[4]?中可以從另一個(gè)角度理解 reduce 中第一個(gè)參數(shù)回調(diào)函數(shù)中接收的第一個(gè)參數(shù):
class?Array?{
??//...
??reduce(callbackfn:?(memo:?any,?value:?any,?index:?number,?target:?any)?=>?any,?initialValue?:?any):?any;
?//...
}
復(fù)制代碼
他這里用的是?memo,中文直接翻譯過來就是備忘錄,在計(jì)算機(jī)中我們或許更為喜歡用緩存。我個(gè)人認(rèn)為是更為符合我們寫出好用的代碼片段的。
他的精髓所在正是將回調(diào)函數(shù)作用于數(shù)組中的各個(gè)成員上,而上一次return的值就作為memo,傳入到下一個(gè)之中,你可以在這里面逐一處理:
不斷更新迭代(累加) 將結(jié)果拼接(扁平化) 將特定的值添加到同一個(gè)對(duì)象之中(字符統(tǒng)計(jì))
最后作為想要得到最終效果展現(xiàn)出來~
總結(jié)

寫代碼,大概是這么幾個(gè)節(jié)點(diǎn)
了解語法 傳參 返回 真正領(lǐng)悟到語言的特性,并能將其運(yùn)用到實(shí)際開發(fā)中,寫出更好更簡(jiǎn)潔更實(shí)用的代碼 多看:要從從這些代碼段中以及網(wǎng)上各路好漢寫的實(shí)用代碼學(xué)習(xí)怎么樣真正地像寫詩一樣寫代碼~ 多寫
第四步的多看,我感覺真的是收益匪淺,如果你有看源碼的學(xué)習(xí)習(xí)慣[5],真的會(huì)學(xué)到很多~ 例如其實(shí)?Redux.compose中也用到了reduce。真的感覺有些代碼,如果我從沒有見到過,我絕對(duì)寫不出來...
關(guān)于本文
來自:前舟
https://juejin.cn/post/7102591881204203557
