理解柯里化,以及在js中的柯里化實現
在電腦科學中,柯里化(Currying)是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數且返回結果的新函式的技術。
簡單的來說柯里化就是把原本多引數的函式,轉換成每次只接受一個引數,但是引數可傳遞的函式鏈來使用。
簡單的例子
// 柯里化前 let plus = (a,b) => a + b plus(1,2)// 輸出:3 // 柯里化後 let plusTwoNum = (a,b)=> a+b let plus = fpu.curry(plusTwoNum) plus(1)(2) // 輸出:3
上面是程式碼是很簡單的一個函式柯里化例子,乍一看是沒有什麼特別的用處的,但是在某些場景是可以發乎很大的用處的,比如說當程式需要執行上面的sum函式,但是引數確實分開獲取的,在某一時刻只能獲取到其中的一個值a,值b需要一定條件後才能拿到的時候就可以使用柯里化來完美的解決這個問題。
下面簡單說一下柯里化的簡單實現(想要支援更復雜的特性,需要自己進行增強)
先上程式碼
// 函式自動柯里化 // eg: new FPUtiles().curry((a,b,c,d) => a+b+c+d)(1)(2)(3)(4) curry(fn){ const _fn = (restNum,argList) => restNum === 0 ? fn(...argList) : x => _fn(restNum-1,[...argList,x]) return _fn(fn.length,[]) }
下面開始整理思路:
- 首先curry函式接收一個函式,這個函式是我們真正的處理邏輯的函式
-
然後通過閉包,宣告一個函式
_fn
,_fn
接收兩個引數,一個是真正函式的引數列表長度的計數器,一個是傳入引數的列表 -
在
_fn
函式中判斷真正函式的引數列表是否等於0,等於0代表引數已經全部都傳入進來了,可以呼叫真正的函式去進行計算,並返回fn
函式進行計算然後返回結果;如果引數列表不等於0,則把引數列表的計數器-1,並把傳入引數進行合併,然後使用返回_fn
函式供尾遞迴呼叫。
上面就是柯里化的大體思路,主要實現是依賴閉包
和尾遞迴
來實現的,所以在效能上有優化的同時也是有一定的損失,對於效能要求很苛刻的程式可能需要酌情考慮,一般情況下合理使用柯里化是可以把程式碼的可讀性下降很多。