js-函數柯里化


內容來自曾探,《JavaScript設計模式與開發實踐》,P49

函數柯里化(function currying)又稱部分求值。一個currying的函數首先會接受一些參數,接受了這些參數后,該函數並不會立即求值,而是繼續返回另外一個函數,剛才傳入的參數在函數形成的閉包里被保存起來。待到函數真正需要求值的時候,之前傳入的參數都會被一次性用於求值。

假設我們要編寫一個計算每月開銷的函數。在每天結束之前,我們都要記錄今天花了多少錢,代碼如下:

var monthlyCost = 0;

var cost = function(money){
    monthlyCost += money;
};

cost(100);//第一天開銷
cost(200);//第二天開銷
cost(300);//第三天開銷
//cost(700);//第三十天開銷

alert(monthlyCost);//輸出:600

這段代碼在每天結束后都會記錄並計算到今天為止花了多少錢,但我們不太關心每天花掉多少,只想知道月底總共花掉了多少,也就是說,只需要在月底計算一次。

如果在每個月的前二十九天,我們都只是保存好當天的開銷,直到第30天才進行求值計算,這就達到了我們的目的。下面的代碼還不是一個currying函數的完整實現,但有助於我們了解其思想:

var cost = (function(){
    var args = [];
    
    return function(){
        if(arguments.length === 0){
            var money = 0;
            for(var i = 0, l = args.length; i < l; i++){
                money += args[i];
            }
            return money;
        }else{
            [].push.apply(args, arguments);
        }
    }
}());

cost(100);//未真正求值
cost(200);//未真正求值
cost(300);//未真正求值

console.log(cost());//求值並輸出:600

接下來編寫一個通用的function currying(){},它接受一個參數,即將要被currying的函數。在這個例子里,這個函數的作用是遍歷本月每天的開銷並求出它們的總和。代碼如下:

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 < l; i++){
            money += arguments[i];
        }
        return money;
    }
}());

var cost = currying(cost);//轉化為currying函數

cost(100);//未真正求值
cost(200);//未真正求值
cost(300);//未真正求值

console.log(cost());//求值並輸出:600    

至此,我們完成了一個currying函數的編寫,當調用cost()時,如果明確帶上參數,表明此時並不進行真正的求值計算,而是把這些參數保存起來,此時讓cost()函數返回另外一個函數。只有當我們以不帶參數的形式執行cost()時,才利用前面保存的所有參數,真正開始求值計算。

 

內容來自曾探,《JavaScript設計模式與開發實踐》,P49


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM