官方解释 柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
个人白话文理解
当一个函数fn有多个参数时,可以先传入一部分参数,生成一个中继函数nextFn,然后在nextFn当中再传入剩下的参数。(一步curry化)
function currying(x, y) {
if (typeof y == 'undefined') {
return function (y) {
return x + y;
};
}
else {
return x + y;
}
}
var nextFn = currying(5);
console.log(nextFn(5)); // 10
function currying(fn) {
var slice = Array.prototype.slice;
// 将arguments对象数组化,并排除第一个参数fn
var args = slice.call(arguments, 1);
return function () {
var newArgs = slice.call(arguments);
return fn.apply(null, args.concat(newArgs));
};
}
// test
function add(a, b, c, d, e) {
return a + b + c + d + e;
}
// 一步curry化
var next = currying(add, 11, 22);
// 两步curry化
var next2 = currying(next, 33);
// 三步curry化
var next3 = currying(next2, 44);
next(33, 44, 55); // 165
next2(44, 55); // 165
next3(55); // 165
参照:http://www.zhangxinxu.com/wordpress/2013/02/js-currying/
curry化之后会返回一个新的函数,这个函数通过闭包保存着重复的参数。
其实ES5当中的Function.prototype.bind
方法运用的就是curry化的思想
if (typeof Function.prototype.bind == 'undefined') {
Function.prototype.bind = function (o) {
var me = this;
var args = [].slice.call(arguments, 1);
return function () {
var newArgs = [].slice.call(arguments);
return me.apply(o, args.concat(newArgs));
};
};
}
看完curry化,第一个感觉是好高大阿,但是…好像目前没感觉到它有什么用耶。。。
其实我觉得张鑫旭的博客JS中的柯里化当中,有段话讲的挺有道理的
最近在看《JavaScript模式》一书,天哪,里面出现的各种设计模式(如工厂模式、外观模式、观察者模式),一双手都数不过来。而且这些名词又很抽象,书一合,马上大眼瞪小眼了。这种感觉就像是,房间里来了10个黑人,每个黑人都有一个“¥%#…¥”的名字,好不容易勉强记住了,灯一关房间一黑,等再开灯的时候,每个黑人的名字都变成…..”hello”了。 其实这些模式在实际使用的时候,或多或少都使用过,当看到“xx模式”概念的时候,我们就会猛然惊起:“哦,原来这个就叫做‘观察者模式’等”。现在要讨论的问题是,我们有没有必要把这些“xx模式”都记住呢,都理解其对应的核心呢? 这个问题类似于,我可以看懂NBA的篮球比赛,那我有没有必要把各个球队以及球队的队员都记住呢? 如果想成为JS大神,从这个目标来看,这是需要的;好比优秀的篮球解说员必须要知道每个球队的名字、球员甚至周边八卦。但是,现实很重要。如果连JS函数相关的基本东西都驾驭不好,显然,硬是啃这些似懂非懂的概念只会造成混乱。如果你觉得可以更近一步,先通透几个自己习惯的熟悉的使用模式,足够应付实际项目;其他一些概念什么的,更多的只是噱头,实用性其实并不大。 正如本文的柯里化,看上去很高级,似乎也有点用处,然而JS的灵活性使得很多实现完全摆脱“柯里化”这个概念的束缚,以更通俗易懂的方式实现。 然而,即使实用性不高,我们还是要有所了解,因为,你不知道什么时候会用到它。比方说CSS中的
display:table;
某些情况下可以解决一些棘手问题(secret!)。 因此,本文的柯里化至少要知道个大概…
var gitalk = new Gitalk({ clientID: '82f3fb6574634b43d203', clientSecret: '5790d9fdbfe9340d29810b694b3b2070a9a3b492', repo: 'zfengqi.github.io', owner: 'zfengqi', admin: ['zfengqi'], distractionFreeMode: true, id: window.location.pathname, }); gitalk.render('gitalk-container');