在函數式編程中柯里化是一個十分重要的概念
那么 什么是柯里化呢?
定義:
只傳遞給函數一部分參數來調用它,讓它返回一個函數去處理剩余的參數。這個過程就叫做柯里化。
實例:
// 未柯里化的函數
function add1(x,y,z){
return x+y+z
}
console.log(add1(10,20,30))
// 柯里化處理的函數
function add2(x){
return function(y){
return function(z){
return x+y+z
}
}
}
// 可以化處理的函數可以簡化成
// var sum2 = x=>y=>z=>x+y+z
console.log(add2(10)(20)(30))
光從上面的例子來看的話,就會覺得函數的柯里化沒有必要,
反而更加復雜化了,但其實不是這樣。
在函數式編程中,我們往往希望一個函數處理的問題盡可能的單一,而不是將一大堆的處理過程都交給一個函數來處理。
那么我們就可以將每次傳入的參數在單一的函數中進行處理,處理完后在下一個函數中再使用處理后的結果。
比如我們那上面的案例進行一個修改:傳入的函數分別需要進行如下的處理
- 第一個參數+2
- 第二個參數*2
- 第三個參數**2
function addx(x){
x=x+2
return function(y){
y=y*2
return function(z){
z=z**2
return x+y+z
}
}
}
另外一個使用柯里化的場景是可以幫助我們實現復用參數邏輯
makeAdder函數要求我們傳入一個num(當我們需要的時候,可以對num進行一些修改)
function makeAdder(num){
return function(count){
return num+count
}
}
var add5 = makeAdder(5)
add5(10)
add5(100)
var add10 = makeAdder(10)
add10(10)
add10(100)
在這里我們演示一個案例 需求是打印一些日志
(包括時間,類型,信息)
// 普通函數的實現方式
function log(date, type, message) {
console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
}
// log(new Date(), "DEBUG", "查找到輪播圖的bug")
// log(new Date(), "DEBUG", "查詢菜單的bug")
// log(new Date(), "DEBUG", "查詢數據的bug")
// 柯里化的優化
var log = date => type => message => {
console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
}
// 如果我現在打印的都是當前時間
var nowLog = log(new Date())
nowLog("DEBUG")("查找到輪播圖的bug")
nowLog("FETURE")("新增了添加用戶的功能")
var nowAndDebugLog = log(new Date())("DEBUG")
nowAndDebugLog("查找到輪播圖的bug")
nowAndDebugLog("查找到輪播圖的bug")
nowAndDebugLog("查找到輪播圖的bug")
nowAndDebugLog("查找到輪播圖的bug")
var nowAndFetureLog = log(new Date())("FETURE")
nowAndFetureLog("添加新功能~")
相信通過上面的總結 大家應該對函數的柯里化的重要性有了一定的認識
那么現在我們在提一個新的需求——我們現在需要一個函數,這個函數能夠將我們傳入的函數自動生成柯里化函數,不需要我們自己再寫一個新的函數
// 柯里化函數的實現
function newCurry(fn){
function curried(...args){
// 判斷當前已經接收的參數的個數,與參數fn本身需要接受的參數是否一致
// 當已經傳入的參數 大於等於 需要的參數的時候,就執行函數
if(args.length >= fn.length){
return fn.call(this,...args)
}else{
// 當已經傳入的參數沒有達到fn的參數個數的時候,需要返回一個函數繼續來接收參數
return curried2(...args2){
// 接收完參數后,需要遞歸調用curried來檢查個數是否已經一致了
return curried.call(this,args.concat(args2))
}
}
}
return curried
}
理解組合函數
組合函數是在js開發過程中的一種對函數的技巧、模式
比如我們現在需要對某一個數據進行函數的調用,執行兩個函數fn1和fn2,這兩個函數是依次執行的
如果我們每一次都需要對兩個函數進行調用,操作上就會顯得重復
所以我們可以將兩個函數組合起來,自動依次調用
這個過程就是對函數的組合,我們稱為組合函數
function double(num){
return num*2
}
function square(num){
return num**2
}
function compose(fn1,fn2){
return function(x){
return fn2(fn1(x))
}
}
var calcFn = compose(double,square)
console.log(calcFn(10))