我們的目標是給定一個初始值以後,用pipeline的方法實現不同函數運算的順序執行,從而得出最終結果。
最終實現應該如下:
var result = pipeline(initialValue, func1, func2, func3...);
首先先寫幾個函數吧:
var double = n => n * 2;
var pow = n => n * n;
var pow3 = n => n * n * n;
這裏用了ES6中的箭頭函數。對於有返回值的函數,用箭頭函數寫出來簡潔而清晰。
函數的順序執行,就想到了前後的函數必須有聯繫。
我們可以用Array. reduce( ) 方法。
詳細描述請見以下鏈接:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
函數式編程的一個基本思想就是,你可以把有返回值的函數當成一個變量在函數中傳參調用。
所以我們可以這麼寫:
funcs.reduce(function(pre,cur){
return cur(pre);
}, val);
這裏初始值爲val, 也就是我們要傳入pipeline計算的那個值。
在首次計算中, pre就是 val, 以後的pre值都是前次的return cur(pre);
稍稍動下腦筋,就知道此功能可以實現當前函數調用前次函數的返回值,從而實現流水線調用。
funcs是一個函數數組,第一我們想到的是用Array.push()。
實際上完全不用這麼麻煩,可以用 … 運算符實現參數列表到數組的轉換,這也是ES6的一個爽點。
貌似說得七七八八了,我們就來封裝一下這個函數:
function pipeline(val, ...funcs) {
return funcs.reduce(function (pre, cur) {
return cur(pre);
}, val);
}
好,接下來我們直接傳參:
var result = pipeline(2, double, pow, pow3); // 4096
完美執行!
可是這就完了嗎?
不!這還沒有get到函數式變成的精髓。
我們是有追求的屌絲碼農。
極簡!極簡!極簡!
那好,咱們就來裝個內什麼吧。。。
改寫下:
var pipeline = (val, ...funcs) => funcs.reduce((pre, cur) => cur(pre), val);
一行代碼搞定!
結果一樣!
var result = pipeline(2, double, pow, pow3); // 4096
而且所傳函數個數不限。
當然,代碼的易讀性很重要。
所以不裝也罷。