高階函式應用--currying

caraline發表於2017-08-22

熱身!

要實現三個幾個數相加,我們一定會這樣寫:

function add(a,b,c){
           return a+b+c;
       }
    var total=add(1,2,3)複製程式碼

對啊,這樣寫沒錯。但是現在我要改需求了,要求--“結合閉包,函式只能有一個引數,並且完成以上能力”,這時候相信你已經想到了要用函式的柯里化來實現,牛逼!

在學習curring之前我們先來認識高階函式

高階函式?

高階函式的特點:

  • 函式可以作為引數被傳遞;
  • 函式可以作為返回值輸出。

顯然,JavaScript語言中的函式就滿足高階函式的條件。在實際開發中也有很多應用,我們現在就講講其中的一個應用--curring!

函式柯里化

curring也稱部分求值。為什麼?來講講它的概念,你就明白了。

一個curring的函式首先會接受一些引數,接受了這些引數後,該函式並不是立即求值,而是繼續返回另外一個函式,剛才傳入的引數在函式形成的閉包中被儲存起來。等到函式被真正需要求值的時候,之前傳入的所有引數都會被一次性用於求值。其實簡而言之就是:把一個接受N個引數的函式轉變成一個接受一個單一引數的函式,並且返回接受餘下引數的新函式。

扔了這麼多幹貨,到解決任務的時候了

柯里化簡單實現:

實現上面要求:

function curriedAdd(a){
        return function(b){
            return function(c){
                return a+b+c;
                console.log(a+b+c);
            }
        }
    }
// 函式巢狀函式自動構成了閉包
curriedAdd(1)(2)(3)複製程式碼

函式只接受一個引數,並且返回一個函式。函式巢狀函式自動構成了閉包,閉合空間的引用一直保留,前兩次都沒有求值,其變數一直保留到最後一次求值。

到這裡大家肯定理解了function curring 了,那我們來個進階!

question:

如果我們要編寫一個計算每個月的開銷的函式。自然,要記錄下每天的開銷再求和。

程式碼實現:

var currying=function(fn){
    var args=[];
    return function(){
        if(arguments.length===0){
            return fn.apply(this,args);
        }else{
            [].push.apply(args,arguments);
            return arguments.callee;
        }
    }
};
var cost=(function(){
    var money=0;
    return function(){
        for(var i=0,l=arguments.length;i<1;i++){
            money+=arguments[i];
        }
        return money;
    }
})();
var cost=currying(cost);//轉化成curring函式
cost(100);//未真正求值
cost(200);//未真正求值
cost(300);//未真正求值

console.log(cost());//求值並輸出:600複製程式碼

這就實現了柯里化的函式。當呼叫cost()時,如果明確地帶上了一些引數,這裡的cost(100),cost(200),cost(300),表示此時並不進行真正的求職計算,而是把這些引數儲存起來,儲存在[]中,此時cost函式返回另外一個函式arguments.callee。只有當我們以不帶引數的形式執行cost()時,才利用前面儲存的所有,真正開始執行求值計算。

如果你覺得收穫了currying,感謝star ?

相關文章