函式的柯里化
阿新 • • 發佈:2018-12-22
看了不少大佬的文章,終於對柯里化有了初步的理解,簡單總結一下。
什麼是柯里化?
在電腦科學中,柯里化(Currying)是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數且返回結果的新函式的技術。
看了概念還是一頭霧水,用程式碼解釋一下。
例如有一個簡單的加法運算:
function add(a,b,c){
return a+b+c
}
add(1,2,3); //這是接受多個引數的函式
現在把它變換成接受單一引數的柯里化函式
function add(a){ return function(b){ return function(c){ return a+b+c } } } add(1)(2)(3); //接受單一引數
柯里化函式結合了閉包的用法,不瞭解閉包的先學習閉包噢
柯里化把簡單的問題複雜化了,同時把複雜的問題自由化了,來看這麼一個例子:
// 實現一個add方法,使計算結果能夠滿足如下預期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4,5) = 15;
這個題目的難點在於引數的不確定,所以要封裝一個函式來運算。
function add(){ //debugger; var args = [].slice.call(arguments); var fn = function(){ var newArgs = args.concat([].slice.call(arguments)); return add.apply(null,newArgs); //null表示window } fn.toString = function(){ //toString()重寫函式 return args.reduce(function(a, b) { //reduce() 方法接收一個函式作為累加器 return a + b; }) } return fn ; } add(1)(2)(3); //f 6 add(1, 2, 3)(4); //f 10 add(1)(2)(3)(4,5) ; //f 15 add(1)(2)(3).toString(); //6
函式有些難理解,建議debugger在瀏覽器看執行步驟。
柯里化的應用場景
手機號、郵箱的驗證,我們一般會寫一個通用的函式,將用於驗證的正則和將要被驗證的字串作為引數傳入。
function check(reg,targetString){
return reg.test(targetString);
}
這樣使用會有點冗餘,每次都要重複寫正則表示式
check(/^1[34578]\d{9}$/, '14900000088');
check(/^1[34578]\d{9}$/, '13714357188');
check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, ' [email protected]');
check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, '[email protected]');
柯里化函式的執行過程其實是一個引數的收集過程,我們將每一次傳入的引數收集起來,並在最裡層處理,所以可以藉助這個思路來封裝一下。
function createCurry(func, args) {
var arity = func.length; //2 check函式形參的長度
var args = args || [];
return function() {
var newArgs = [].slice.call(arguments);
[].push.apply(newArgs, args); //args引數push進newArgs
// 如果引數個數小於最初的func.length,則遞迴呼叫,繼續收集引數
if (newArgs .length < arity) {
return createCurry.call(this, func, newArgs);
}
// 引數收集完畢,則執行func
return func.apply(this, newArgs );
}
}
var checkPhone = createCurry(check)(/^1[34578]\d{9}$/);
var checkEmail = createCurry(check)(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
最後呼叫就會更加簡潔了。
checkPhone('14900000088');
checkPhone('13714357188');
checkEmail('[email protected]');