從數(shù)組Reduce中構(gòu)建Map等12個函數(shù)
如我們所知,JavaScript是當今流行語言中對函數(shù)式編程支持最好的編程語言。而函數(shù)式編程"從一到無窮”的起點是 reduce,本文我們將嘗試從 reduce 起步構(gòu)建所有的其他函數(shù)。

一、萬物之始 array.reduce 的應(yīng)用
Reduce的核心在于降維,將數(shù)組reduce為一個值,比如求和:
- const arr = [52, 71, 27, 38];
- const sum = (x, y) => x + y;
- const cusSum = arr.reduce(sum, 0);
將reduce作為思考工具,腦子中要始終留有 initial-value 初始值。
二、構(gòu)建 array.map 從數(shù)學到編程
map是數(shù)學思維而直接入編程,從reduce中模擬構(gòu)建為:
- const cusMap = (arr, fn)
- => arr.reduce((x, y)
- => x.concat(fn(y)), []);
三、構(gòu)建 array.flat array.flatMap 拍平數(shù)組
從array.flat我們窺探到 declaratively 編程的優(yōu)勢,只須將精力專注到要完成的任務(wù)上,而不必理會實現(xiàn)細節(jié)。用 reduce 實現(xiàn)為:
當只 flat 到一層深度時候:
- # flat only to one level
- const flat1 = arr => [].concat(...arr);
- const flat2 = arr = arr.reduce(acc, v => acc.concat(v), [])
當需要 flat 到任意深度時, 用 reduce 完全重構(gòu) flat:
- if (!Array.prototype.flat) {
- Array.prototype.flat = function(n = 1) {
- this.flatAllX = () =>
- this.reduce(
- (f, v) => f.concat(Array.isArray(v) ? v.flat(Infinity) : v),
- []
- );
- this.flatOneX = () => this.reduce((f, v) => f.concat(v), []);
- return n === Infinity
- ? this.flatAllX()
- : n === 1
- ? this.flatOneX()
- : this.flatOneX().flat(n - 1);
- };
- }
四、array.filter 邁向高階的邏輯判斷 logic predicate
為什么要用 reduce 重新構(gòu)建,因為能夠幫助在頭腦中始終擦亮 function 與 最終輸出 acculator 的概念。
- const cusFilter = (arr, fn)
- => arr.reduce((acc, val)
- => (fn(val) ? acc.concat(y)
- : acc), []);
五、array.find 與 array.findIndex 只找出首個元素
array.filter將會篩選出來全部的符合要求的元素,當我們只要單個元素的時候則應(yīng)用 array.find.
- const cusFind = arr.reduce((acc, val)
- => (acc === undefined && fn(val) ? val
- : acc), undefined);
重新構(gòu)建 array.findIndex:
- const cusFindIndex = arr.reduce((x, y, i)
- => (x == -1 && fn(y) ? i
- : x), -1);
進而,我們用 find 與 findIndex 簡單的構(gòu)建 includes 與 indexOf。
- arr.includes(value); // arr.find(v => v === value)
- arr.indexOf(value); // arr.findIndex(v => v === value)
六、快捷的 array.some 與 array.every
array 與 some 兩函數(shù)雖然簡單,思考和使用的時候尤其順手。
- // arr.every(fn);
- arr.reduce((a, v) => a && fn(v), true); // a for accumulator,
- // arr.some(fn);
- arr.reduce((a, v) => a|| fn(v), false); // v for value
至此,我們從reduce出發(fā),將其他幾個高階函數(shù)全部模擬出來,reduce模擬幫助我們強化對每個函數(shù)中輸入的arguments與輸出的 result 的辨識。