一、柯里化
在定義柯里化、部分應用引數的概念前,首先必須對閉包有深入的瞭解和定義,閉包一句話說清楚:函式返回值為函式。
柯里化的定義:將多參函式分解為按步驟接受單個引數的函式,如下程式碼:
var mod = function(a,b){ return a * b; } function curry2(fun){ var _funTwo = function(arg){ return function(two){ return fun(arg,two); } }; return _funTwo; } var _add2 = curry2(mod); var result2 = _add2(1)(2);
mod:接受兩個引數,分別為a,b;
curry2:實現柯里化功能函式,由於傳入mod這個引數,返回接受一個引數的閉包;在新閉包的函式上傳入另一個值(b)即可完成mod函式的執行。
無限級柯里化
var mod = function(a,b){ return a * b; } function curry2(fun){ var newVal; var _funTwo = function(arg){ return function(two){ if(!two) return newVal; newVal = fun(arg,two); return _funTwo(newVal); } }; return _funTwo; } var _add2 = curry2(mod); var result2 = _add2(1)(2)(3)(4)(5)();
1.2、柯里化的應用
a). 利用柯里化增加約束條件,只有通過所有約束條件的資料才最終被執行;
b). 變數不會存在全域性汙染(保護變數的私有性),自由變數(函式內部不定義,但可以訪問的變數,一般情況下是全域性變數,或區域性全域性變數),約束變數(函式內部定義的變數,生命週期在函式內部)。函式(function)依賴自由變數,就會存在自身的返回值不可控的現象,這就是傳說中的共享變數耦合。
c). 無限級柯里化固能實現,但不實用,用柯里化最主要的目的是為最終執行單元增加約束條件(引數分解),約束條件是有限的。
如需要約束條件是動態的,則應該選擇下面介紹的”部分應用引數“
二、部分應用引數
部分應用引數的定義:傳入任何多個約束條件,返回接受執行單元和引數的閉包。實現約束條件的預設定。程式碼如下:
function Parit(fun, parg){ return function(){ var args = _.toArray(arguments); args.splice(0,0,parg); return fun.apply(fun,args); //執行後必須返回 } } function condition1(){ var validators = _.toArray(arguments); return function(fun, arg){ var errors = _.map(validators,function(data,irow){ return data(arg) ? [] : [data.name + ' error']; }); if(!_.isEmpty(errors.join())){ console.info(errors.join()); return; //throw new Error(errors.join()); } return fun.call(fun,arg); //執行後必須返回 } } var sqlPre = condition1(_.isNumber); //sqlPre是閉包,需要fun,arg兩個引數 function uncheckedSqr(n){ return n * n; } console.log(sqlPre( uncheckedSqr,10) ); //本質 var sqr = Parit(sqlPre,uncheckedSqr); //返回一個閉包 uncheckedSqr作為sqlPre的第一個引數傳入 console.log( sqr('5') ); console.log( sqr(5) );
2.2、部分引數應用:
a). 實現約束預設定,主要用於驗證模組。
b).部分應用引數與柯里化主要區別於,柯里化每次只接受一個引數,而部分應用引數一次可以接受多個引數;但柯里化與部分應用引數都只能按照引數進行組合 。
三、總結
a). 柯里化的理解是javascript進階的基礎,在函數語言程式設計中是極其重要一環。函數語言程式設計主要講究資料的不變性、集合操作、尾遞迴等。