什么是柯里化?
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
以上是维基百科对于柯里化给出的定义,总结一下:
- 输入是一个函数,并且这个函数拥有n个参数
- 输出也是一个函数,并且可以使用
fn()()()
这种方式调用 - 参数被柯里化过程中的函数被拆分
写一个经典的用来解释柯里化的例子:
function add(a, b, c) {
return a + b + c;
}
const addTen = curry(add, 10); // curry就是后续我们将实现的 柯里化函数
addTen(1)(2) // 13
addTen(3, 4) // 17
不难看出柯里化的用途之一就是参数复用,我们可以通过柯里化的方式很方便的实现参数复用,可能这样你感觉没啥卵用,再来看下面例子:
const amount = [
{ deposit: 120, finalPayment: 200 },
{ deposit: 110, finalPayment: 300 },
{ deposit: 130, finalPayment: 100 },
];
// 按照deposit的值对数组进行排序
// 很容易想到这么做
amount.slice().sort((a, b) => a.deposit - b.deposit);
// 后来又需要对finalPayment进行排序
amount.slice().sort((a, b) => a.finalPayment - b.finalPayment);
// 我们再来使用柯里化的形式重新写一下
const sort = curry(function(field, a, b) {
return a[field] - b[field];
})
console.log(amount.slice().sort(sort('deposit'))); // deposit进行排序
console.log(amount.slice().sort(sort('finalPayment'))); // finalPayment进行排序
简而言之:JavaScript中的柯里化其实是利用闭包的特性,将所有参数都搜集到之后再一并执行。
function fn(a, b, c, d, e...) {}
// 通过柯里化 转换为
curryFn(a)(b)(c)(d)(e)(...)
如何实现柯里化?
对于add(a, b) {}
这样的函数我们很容易柯里化它
function add(a, b) {
return a + b;
}
function curry(fn, a) {
return function(b) {
return fn(a, b);
}
}
curry(add, 10)(1); // 11
没啥毛病,那我想做一个传入三个参数的函数柯里化咋办呢?安排~
function curry(fn, a) {
return function(b) {
return function(c) {
return fn(a, b, c);
}
}
}
那四个参数咋办呢。。。很明显这种方式并不具备通用性,其实仔细观察上面的代码,仿佛,似乎,可能递归能实现:
function curry(fn, ...args) {
return function(...innerArgs) {
const allArgs = [...args, ...innerArgs];
if (fn.length <= allArgs.length) {
// 说明已经接受完所有参数,这个时候可以执行了
return fn.apply(this, allArgs);
} else {
// 继续返回函数,收集参数
return curry(fn, ...allArgs);
}
}
}
以上就是关于柯里化的知识,希望对各位童鞋有所帮助。