在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
以上是来自维基百科的名词解释,有点绕。简而言之,柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果。
因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程。
先来看一下柯里化的通用实现:1
2
3
4
5
6
7
8function currying(fn) {
var slice = Array.prototype.slice,
__args = slice.call(arguments, 1);
return function () {
var __inargs = slice.call(arguments);
return fn.apply(null, __args.concat(__inargs));
};
}
解读一下这段代码:
- line 2 & line 3 : Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组,除了IE下的节点集合(因为ie下的dom对象是以com对象的形式实现的,js对象与com对象不能进行转换),所以这里是除了fn之外的参数全部转化为了数组
- 接下来的 line 4/5/6/7 其实是返回了一个闭包
- line 5 将闭包函数内的参数转化为数组 __inargs
- line 6 执行传入的fn函数,其参数为两次传入参数的集合
- 注:当apply传入null/undefined为第一个参数的时候将执行js全局对象,浏览器中是window,其他环境是global。
柯里化的实用性提现在很多方面:
1 提高适用性
根据以上代码我们来做一个简单的实现:
1 |
|
由此,可知柯里化不仅仅是提高了代码的合理性,更重的它突出一种思想—降低适用范围,提高适用性。
2 延迟执行
柯里化的另一个应用场景是延迟执行。不断的柯里化,累积传入的参数,最后执行。以下是其通用写法:1
2
3
4
5
6
7
8
9
10var curry = function(fn) {
var _args = []
return function cb() {
if (arguments.length == 0) {
return fn.apply(this, _args)
}
Array.prototype.push.apply(_args, arguments);
return cb;
}
}
3 固定易变因素
柯里化特性决定了它这应用场景。提前把易变因素,传参固定下来,生成一个更明确的应用函数。最典型的代表应用,是bind函数用以固定this这个易变对象。
1 |
|