js之函式柯里化
阿新 • • 發佈:2018-11-29
函式柯里化是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原型上的,一個是返回一個物件的值,預設是本身,一個是返回物件字串)