函數柯里化:柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數且返回結果的新函數的技術。是否有些不太懂?好吧,用段代碼來解釋下。html
function saySTS(something) {前端
return function(someboby) {ajax
alert(something + "!" + sombody);編程
}json
}閉包
saySTS函數就是用來講些什麼(something)對某人(somebody);這就是柯里化的函數。dom
-------------------------------------------------------------------------------------------------------------------------------------------------------異步
咱們來看下若是不用柯里化來怎麼實現。async
function saySTS(something, somebody){函數式編程
alert(something + "!" + sombody);
}。
--------------------------------------------------------------------------------------------------------------------------
也許你會問我函數柯里化到底有什麼用,不就是把多個參數的函數轉換成多個單參數函數嗎?下面我拿實際前端開發中的例子來解釋。
如今有這麼一個問題模型:
你要開發一個抽獎活動頁面,後臺開發人員要跟您定一個抽獎接口,這個接口會根據不一樣的抽獎選項返回不一樣的抽獎信息。請求的接口的幾個地址:"action.do?state=0","action.do?state=1","action.do?state=2".
假如這些接口是根據3種不一樣積分,來進行相應的抽獎活動,30積分抽獎的獎品,60積分抽獎的獎品,120積分抽獎的獎品,返回的接口多是{中獎信息,抽獎剩餘分數,中獎紀錄,抽了多少次獎,剩餘抽獎次數等等}。
此時你前端有6處須要根絕返回的接口數據進行顯示或者交互操做,簡化一點div#01, div#02, div#03, div#04, div#05, div#06.這幾塊要顯示剩餘的抽獎次數。
若是不用柯里化我會這樣作
function render(url) {
$.ajax({
type:"post",
url:url,
cache:false,
async:true,
dataType:"json",
data:params,
//當異步請求成功時調用
success: function(data, status){
//此行可能你還須要對數據進行一些處理。總之在你拿數據渲染你的dom節點前或許還要作點別的。
$("div#01").html(data.times);//例子比較簡單,可能你須要作的不僅這些還有不少。抽獎的提示信息。
//等等其餘操做.......
},
//當請求出現錯誤時調用
error: function(err){
alert("error : "+err);
}
})
}
很顯然這樣的代碼耦合性很強,不太利於擴展跟維護.並且返回的數據我也不必定非得作html(data.times)這樣的操做。把返回後的信息所有集中處理,這樣不好。
改進下咱們把成功以後的要處理的操做單獨提取出來放在一個咱們都會叫出來的名字callback
function callback(item, data) { //終於把耦合的代碼搞出來了,item多是div#01, div#02, div#03, div#04, div#05, div#06
$(item).html(data.times);
}
//這裏咱們假設後臺人員只開發了一個接口,以致於我想查詢剩餘次數顯示在相應的信息欄上也要返回(最近中獎紀錄,剩餘分數等)這些數據
//固然這是很失敗的接口,通常接口只須要返回前端想要的數據便可。
function callback02(item, data) { //也許我也想作callback02這樣的操做等,render都是能夠支持的
return function(data){
$('item').click(function(e){
alert(data.gift);
})
}
}
function render(url, item, callback) {
$.ajax({
//一些代碼不重複
success: function(data, status){
//此行可能你還須要對數據進行一些處理。總之在你拿數據渲染你的dom節點前或許還要作點別的。
callback(item, data);
},
error: function(err){
alert("error : "+err);
}
})
}
這樣咱們就能夠對div#01 div#02 等要操做的dom節點靈活的,並且操做方式能夠多變化。
可是有一天忽然要作這麼一件事兒,我不光要顯示剩餘次數,並且還要把禮品等等一切信息在前端顯示出來
function callback03(data) { //這個過程不只僅想知道msg或者gift
//針對一個前端抽獎模塊進行全面的渲染。
//不一樣的幾個前端模塊我要顯示全部關於本人中獎的信息(抽中多少次,中過什麼獎啊等等)
}
等等,咱們的render函數有三個參數,這個callback03是否是不符合規定啊,咱們還須要item
由於render裏面的callback咱們是這樣調用的callback(item, data);
很顯然render已經不適合新的callback03了,再寫一個差很少的render?重複不少代碼只是在callback(item, data)有些不同的新的處理函數?
不,顯然不須要,咱們不能這樣作,這是很冗餘的。那咱們怎麼辦?
您可能在想:come on!My man(丹澤爾華盛頓在美國黑幫的一句口頭禪,非常喜歡),來點正題吧!
好吧,來個柯里化過的函數吧。
首先改變render函數改爲更靈活的。讓他專一於作一件事。就是處理callback,不要加上item。
function render(url, callback) {
$.ajax({
//一些代碼不重複
success: function(data, status){
//此行可能你還須要對數據進行一些處理。總之在你拿數據渲染你的dom節點前或許還要作點別的。
callback(data);
},
error: function(err){
alert("error : "+err);
}
})
}
但是callback, callback02個人這兩個小夥伴們怎麼辦? 若是你給改了他們兩個要怎麼辦?由於render已經不支持他們了。
別急,咱們把這兩個小夥伴們打扮下。
function update(item) {
return function(data) {
$(item).html(data);
}
}
function update02(item) {
return function(data){
$('item').click(function(e){
alert(data.gift);
})
}
}
function render(url, callback) {
$.ajax({
//一些代碼不重複
success: function(data, status){
//此行可能你還須要對數據進行一些處理。總之在你拿數據渲染你的dom節點前或許還要作點別的。
callback(data);
},
error: function(err){
alert("error : "+err);
}
})
}
render("action.do?state=0", update("div#01"));
render("action.do?state=0", update("div#02"));
render("action.do?state=0", update02("div#01"));
render("action.do?state=0", update02("div#02"));
柯里化是函數式編程重要標誌,這個demo藉助匿名和閉包完成了函數柯里化,函數式編程一切皆爲函數。函數式編程靈活性和執行效率很高,可是總體邏輯不太好捋。
但願你們能提出一些本身的建議。