題目描述
/**
* 函數組合運行
* 說明:實現一個方法,可將多個函數方法按從左到右的方式組合運行。
* 如`composeFunctions(fn1,fn2,fn3,fn4)`等價於`fn4(fn3(fn2(fn1))`。
* 示例:
* const add = x => x + 1;
* const multiply = (x, y) => x * y;
* const multiplyAdd = composeFunctions(multiply, add);
* multiplyAdd(3, 4) // 返回 13
*/
分析
由於ES6給數組新增了reduce方法,所以該功能實現起來比較方便。reduce函數接收兩個參數:迭代函數(該函數有四個參數)和迭代的初始值(可選)。於是我們寫出如下的代碼:
function composeFunctions(...fns) {
return function (arg) {
return fns.reduce((args, fun) => fun(args), arg)
}
}
但是這種寫法有一個問題,就是迭代的第一個函數只能接受一個參數。聰明的你可能想到了擴展運算符,但是你會發現簡單的在arg參數前面加…之後並不會得到我們預期的結果。解決方案如下:
通過參數解構賦值的方式把第一個迭代的函數改造爲單參數的形式:const multiply = ([x, y]) => x * y;
通過數組把參數包裹起來,實現單參數,然後在接收的地方使用擴展運算符將其展開就可以了。
代碼展示
const add = x => x + 1;
const multiply = ([x, y]) => x * y; // 將第一個迭代的函數改造成單參數(數組參數)
function composeFunctions(...fns) {
return function (...arg) { // 在此處對參數進行解構
return fns.reduce((args, fun) => fun(args), arg)
}
}
const multiplyAdd = composeFunctions(multiply, add);
console.log(multiplyAdd(3, 4)); // 13
寫在後面
這種組合的編程思想是很有用的,將一個個單一職責的函數組合起來實現不同的需求,可以最大限度的實現函數的複用。而且這種複用在很多情況下要比繼承好得多。