函數柯裏化
阿新 • • 發佈:2019-03-14
argument this 拆分 思想 [] array 性能 換來 href
1.什麽是柯裏化
柯裏化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受余下的參數且返回結果的新函數的技術。(百度百科搜一下就有)。
從一個普通函數得到一個柯裏化函數的過程叫做函數的柯裏化,返回的函數稱為經過柯裏化的函數。
函數柯裏化的技術來自於一種編程思想,就是一個復雜的問題可以通過分步的方式來求解,分步可以保證代碼邏輯的清晰易懂。
2.舉個例子
function add_1(a,b,c){//普通函數 return a+b+c } console.log(add_1(1,2,3)) function add_2(a,b){//柯裏化函數 return function(c){ return a+b+c } } console.log(add_2(1,2)(3)) function add_3(a){//柯裏化函數 return function(b){ return function(c){ return a+b+c } } } console.log(add_3(1)(2)(3)) function curry(func){//函數的柯裏化過程 return function(a,b){ return function(c){ return func(a,b,c) } } } function curry2(func){//函數的柯裏化過程 return function(a){ return function(b){ return function(c){ return func(a,b,c) } } } } var add_2=curry(add_1) var add_3=curry2(add_1)
我們可以通過分步的return來實現參數的分步傳遞,將add_1這個普通函數變為add_2或者add_3的過程稱為函數的柯裏化。可以預見隨著傳參的不斷增加,柯裏化過程就要不斷的增加,是否可以從curry1,curry2這兩個柯裏化過程中得出一個通用的函數呢?這就是柯裏化函數的通用式。
柯裏化函數的運行過程其實是一個參數的收集過程,我們將每一次傳入的參數收集起來,最後傳給函數執行。function add_n(func,args){//func是表示處理函數;args表示所有參數 let length=func.length;//函數的形參個數,決定了要柯裏化的次數 var args=args || [];//柯裏化時依次收集的參數存儲變量,包含了所有已收集的傳參 return function(){ let _args=Array.from(arguments);//收集柯裏化時函數參數 [].push.apply(_args,args);//將本輪柯裏化運行時的參數添加到已收集的參數數組 if(_args.length<length){//如果參數未收集完,即已收集的參數個數小於函數的形參個數時,遞歸調用 return add_n.call(this,func,_args); } //當全部參數收集完成時,將所有參數傳入函數中執行 return func.apply(this,_args) } } var test=function(a,b,c){ return a+b+c } var test_curry1=add_n(test) var test_curry2=add_n(test,[1]) test_curry1(1)(2)(3) //6 test_curry2(2)(3) //6
3.實際的應用場景
理解了柯裏化的過程,就要註意柯裏化的思想更為重要,可以用來拆分邏輯。一個關於校驗的例子:
function check(partner,str){ return partner.test(str) } function check_curry(partner){ return function(str){ return partner.test(str) } } var check_phone=check_curry(/^1[34578]\d{9}$/) var check_email=check_curry(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/) //使用時較為復雜難用 check(/^1[34578]\d{9}$/,‘18057192235‘) check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/,‘[email protected]‘) //使用時更為清晰明了 check_phone(‘18057192235‘) check_email(‘[email protected]‘)
在柯裏化的實現中,我們知道柯裏化雖然具有了更多的自由度,但同時柯裏化通用式裏調用了arguments對象,使用了遞歸與閉包,因此柯裏化的自由度是以犧牲了一定的性能為代價換來的。只有在情況變得復雜時,才是柯裏化大顯身手的時候。
參考文章:https://www.jianshu.com/p/5e1899fe7d6b
函數柯裏化