在以前的文章中對函數式編程作了一個簡單的概述,在這篇文章中對一個你們喜聞樂見的話題——函數的柯里化進行一個總結。編程
⚠️注意: 柯里化和偏應用的概念常常被混用,在文中會有概念上的簡單區分數組
這些概念仍是很好理解的,咱們的平常開發中老是伴隨着這些函數:app
let log = (msg) => {console.log(msg)}
複製代碼
let add = (x,y) => {return x+y}
複製代碼
argements
獲取全部參數,如今咱們每每會使用 ...args
由於這樣咱們能夠直接使用數組方法進行操做,形如function logAll(){
// arguments 不是數組,只是一個類數組對象
console.log(arguments);
}
logAll(1,2,3); // [1,2,3]
function logAllByES6(...arg){
// arg是數組,能夠執行數組方法
console.log(arg.map((item)=>{return item*2}));
}
logAllByES6(1,2,3) // [2,4,6]
複製代碼
根據一個相對通用的定義,函數的柯里化指:函數式編程
把一個多參數函數轉換爲一個嵌套的一元函數的過程函數
有一個很是典型的例子是add函數優化
// 柯里化前
function add(x,y){
return x+y;
}
add(1,2); // 3
// 柯里化後
function addCurried(x){
return function(y){
return x+y;
}
}
addCurried(1)(2); //3
複製代碼
這樣作的好處在於咱們能夠經過這樣的方式獲得一系列新函數,從而讓咱們優化數據的處理過程ui
偏應用又稱做部分應用,偏應用的概念和柯里化有所區別,可是又很相似spa
事實上有不少文章中的柯里化指的就是偏應用,好比:code
function add(x,y,z){
return x+y+z;
}
add(1,2,3); // 6
// 柯里化
addcurried(1)(2)(3); // 6
// 偏應用
addPartial(1,2)(3); // 6
addPartial(1)(2,3); // 6
複製代碼
實現的方式多種多樣,寫這篇文章的時候也參考了不少前輩的文章,有各類版本的實現,在ES6
的加持下還出現了「一行代碼實現柯里化」這樣的騷操做對象
不過在這裏,我選擇了比較容易被你們接受的實現方法記錄在文中
如下實現方法參考了 Anto Aravinth
的實現,並作了一點小小的改動
let curry = (fn) => {
return function curriedFn(...args){
if(args.length < fn.length){
return function(...args2){
return curriedFn.apply(null,args.concat(args2));
}
}
return fn.apply(null,args);
}
}
let tipFunc = () => {console.log("經過柯里化,令 tipFunc 在指定事件後執行")}
let tipsTimer = curry(setTimeout)(tipFunc);
tipsTimer(10000); // 10s 後執行
tipsTimer(20000); // 20s 後執行
複製代碼
// 偏應用函數
let partial = (fn,...partialArgs)=>{
let args = partialArgs;
return function(...fullArgs){
let arg = 0;
for(let i = 0;i < args.length && arg < fullArgs.length;i++){
if (args[i] === undefined){
args[i] = fullArgs[arg++];
}
}
return fn.apply(null,args);
}
}
let timer10s = partial(setTimeout,undefined,10000);
partial(()=>{console.log("經過偏應用,爲setTimeout函數預先提供參數")});
複製代碼