js之函數柯裏化
阿新 • • 發佈:2018-11-29
添加 調用 通用 || args 基礎 柯裏化 再次 編程
函數柯裏化是js函數式編程的一項重要應用,柯裏化是一種將使用多個參數的一個函數轉換成一系列使用一個參數的函數的技術。假設我們要計算一個表達式如下
function add(a,b,c){ return a+b+c; } add(1,2,3);//直接調用輸出 add(1)(2)(3);//參數分開調用輸出
第一種是我們常見的,第二種參數分開調用不常見,但我們也能實現他 如下
function add(a){ return function(b){return function(c){ return a + b + c; } } }
顯然 ,這樣的寫法很受參數個數的限制,比較不現實,那麽我們需要一個通用函數來實現以上函數功能,這就是基礎版的函數柯裏化
var curry = function(func){ var args = [].slice.call(arguments,1); // 首先我們對通用函數截取參數 return function(){var newArgs = args.concat([].slice.call(arguments)); //將每次添加的函數連接起來 return func.apply(this,newArgs); //將此函數的數組賦給目標函數 並傳入參數 } } function sub(a,b){ return a-b; } var subcurry = curry(sub,5); console.log(subcurry(3));
此函數能實現傳入不同函數,即在curry(sub,5,3)直接傳入參數,或者向上面一樣再次傳參,或許細心的人已經看出來了,這不就是上面第二種寫法,這的確是這樣的,因為他還不能實現subcurry(5)(3);這樣的操作,別急,這只是讓你熟悉下柯裏化的過程,其實柯裏化的核心就是在自我簡化,當一個函數需要多個參數時,我們可以層層簡化,使得我們的參數變換更隨意,雖然一定程度上讓代碼更復雜了。接下來是改進版
function add(a,b){ return a + b; } var currys = function(fn,args){ var length = fn.length; //計算期望函數的參數長度 args =args || []; //利用閉包特性保存參數 return function(){ newArgs = [].slice.call(arguments); //將自身函數參數賦給新參數 [].push.apply(newArgs,args); //將上回保留的參數push進新的數組 if(newArgs.length<length){ //判斷當前函數的參數是否與期望函數參數一致 return curry.call(this,fn,newArgs); //如果不夠,遞歸調用 }else{ return fn.apply(this,newArgs); // 如果夠,就執行期望函數 } } } var addcurry = currys(add); console.log(addcurry(1)(2));
這裏首先用addcurry綁定add函數,然後在進行傳參,每執行一次就傳入一個參數,直到所有參數傳入完成就會執行期望函數 add。
當然,這只是一個改進版的通用柯裏,他限制與特定的參數,如果想要不限定參數,則需要進一步修改,這裏就不做出過多解釋,可以自己去百度,因為這裏需要自己去多琢磨才能搞懂,而不是看一篇博客就能搞懂,這裏給出一到面試題
實現一個add方法,使得計算結果能滿足一下表達式
add(1)(2)(3 ) =6;
add(1,2,3)(4)=10;
add(1)(2)(3)(4)(5) =15;
這裏由於要將進行參數個數不確定計算,這裏就要在函數內部重寫toSting方法或者valueOf方法(這兩個方法都是Object原型上的,一個是返回一個對象的值,默認是本身,一個是返回對象字符串)
js之函數柯裏化