定義
函數(shù)柯里化是這樣的一個轉(zhuǎn)換過程,把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(注:最初函數(shù)的第一個參數(shù))的函數(shù),如果其他的參數(shù)是必要的,返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)。所謂“柯里化”就是使函數(shù)理解并處理部分應(yīng)用。
function curry(func){
var args = [].slice.call(arguments,1),self = this;
return function(){
var newArgs = args.concat([].slice.call(arguments,0));
func.apply(self,newArgs);
}
}
function say(name,tosay){
console.log(name + tosay);
}
var tosay = curry(say,"tiger");
tosay("nihao");
tosay("byebye");
作用
概括起來有三個作用:1. 參數(shù)復(fù)用;2. 提前返回;3. 延遲計(jì)算/運(yùn)行。
參數(shù)復(fù)用
上面的例子就是一個應(yīng)用,參數(shù)name被復(fù)用。
提前返回
很常見的一個例子,兼容現(xiàn)代瀏覽器以及IE瀏覽器的事件添加方法。我們正常情況可能會這樣寫:
var addEvent = function(el, type, fn, capture) {
if (window.addEventListener) {
el.addEventListener(type, function(e) {
fn.call(el, e);
}, capture);
} else if (window.attachEvent) {
el.attachEvent("on" + type, function(e) {
fn.call(el, e);
});
}
};
上面的方法有什么問題呢?很顯然,我們每次使用addEvent為元素添加事件的時候,(eg. IE6/IE7)都會走一遍if...else if ...,其實(shí)只要一次判定就可以了,怎么做?–柯里化。改為下面這樣子的代碼:
var addEvent = (function(){
if (window.addEventListener) {
return function(el, sType, fn, capture) {
el.addEventListener(sType, function(e) {
fn.call(el, e);
}, (capture));
};
} else if (window.attachEvent) {
return function(el, sType, fn, capture) {
el.attachEvent("on" + sType, function(e) {
fn.call(el, e);
});
};
}
})();
初始addEvent的執(zhí)行其實(shí)值實(shí)現(xiàn)了部分的應(yīng)用(只有一次的if...else if...判定),而剩余的參數(shù)應(yīng)用都是其返回函數(shù)實(shí)現(xiàn)的,典型的柯里化。
延遲計(jì)算/運(yùn)行
想知道12月份4個周末總共釣了幾斤魚,可能就會下面這樣實(shí)現(xiàn):
var fishWeight = 0;
var addWeight = function(weight) {
fishWeight += weight;
};
addWeight(2.3);
addWeight(6.5);
addWeight(1.2);
addWeight(2.5);
console.log(fishWeight); // 12.5
若是有柯里化實(shí)現(xiàn),則會是下面這樣:
var curryWeight = function(fn) {
var _fishWeight = [];
return function() {
if (arguments.length === 0) {
return fn.apply(null, _fishWeight);
} else {
_fishWeight = _fishWeight.concat([].slice.call(arguments));
}
}
};
var fishWeight = 0;
var addWeight = curryWeight(function() {
var i=0; len = arguments.length;
for (i; i<len; i+=1) {
fishWeight += arguments[i];
}
});
addWeight(2.3);
addWeight(6.5);
addWeight(1.2);
addWeight(2.5);
addWeight(); // 這里才計(jì)算
console.log(fishWeight); // 12.5
本部分主要是參考了JS中的柯里化(currying)這邊文章,希望大家去看原文。