上次我寫了一篇簡單介紹函數式思惟的文章,咱們組的同窗看了以後表示很感興趣,但願我有空多寫寫這方面的內容,而後表示他能想到用數組的 map,可是想不到 reduce。我想這可能也是個廣泛現象,由於在對 FP(函數式編程)接觸很少的同窗來說,腦海中對 map 的印象,可能基本等同於循環,而對 reduce 就相對陌生。但其實呢,reduce 是個比 map、flatMap 啥的更通用的函數,你能夠用 reduce 輕易地實現其餘函數。編程
咱們先實現一下 reduce:數組
const reduce = (reducer, acc) => list => {
const [head, ...rest] = list;
if (head === undefined) return acc;
return reduce(reducer, reducer(acc, head))(rest);
};
複製代碼
JS 裏 Array.prototype.reduce 跟我這個稍有不一樣,它的 reducer 能夠接收四個參數(比個人版本多了 currentIndex 和 array),有 currentIndex 這個參數,就告訴咱們它的實現大機率是經過循環作的,說實話我的感受後面兩個參數基本是沒用的,其餘語言裏的實現通常也沒這兩個參數。函數式編程
而後再解釋下爲啥個人 reduce 不是直接接收三個參數,而要用部分應用的形式,先接收兩個,返回一個接收一個參數的函數呢?是爲了複用,咱們看個例子,用 reduce 實現一個 sum 函數,把數組裏的元素都累加起來:函數
const arr = [1, 2, 3]; // 下文全部的 arr 都是這個
const sum = reduce((acc, x) => acc + x, 0);
sum(arr); // => 6
複製代碼
reduce 在接收不一樣的 reducer 和 acc 的時候會返回不一樣的函數,這裏是返回 sum,是否是就很順。而若是 reduce 是一個接收三個參數的函數,那 sum 就得是const sum = (arr) => reduce((acc, x) => acc + x, 0, arr)
,也不是不能夠,但比較醜陋。ui
接下來咱們用 reduce 實現數組的其餘方法:length、map、flatMap、includes、findthis
// JS 的 Array.length 跟我這個實現不同,
// arr[100] = 1,arr.length 就爲 101 了,由於 JS 的 Array 本質是對象
const length = reduce(acc => acc + 1, 0);
length(arr); // => 3
const map = func => reduce((acc, x) => [...acc, func(x)], []);
map(x => x + 1)(arr); // => [2, 3, 4]
const flatMap = func => reduce((acc, x) => [...acc, ...func(x)], []);
flatMap(x => [x + 1])(arr); // => [2, 3, 4]
const includes = element => reduce((acc, x) => acc || (x === element), false);
includes(1)(arr); // => true
// 找到第一個符合條件的元素返回,不然返回 undefined
const find = func => reduce((acc, x) => acc || (func(x) ? x : undefined), undefined);
find(x => x > 2)(arr); // => 3
複製代碼
咱們有時候處理字符串,也會想用到 reduce、map 啥的,那咱們就給 String.prototype 加上:spa
// string
String.prototype.reduce = function (reducer, acc) {
return reduce(reducer, acc)(this.split(''));
};
String.prototype.map = function (func) {
return map(func)(this.split('')).join('');
};
const str = '123';
str.reduce((acc, x) => acc + Number(x), 0); // => 6
str.map(x => Number(x) + 1); // => '234'
複製代碼
emmmmmmm……就這樣吧。prototype