Mark24
JavaScript编程之函数柯里化
柯里化(Currying)
维基百科定义:
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
从一个例子理解合理化
有点复杂,简单表达:
函数柯里化(curry)可以简单的理解是将具有多个参数的函数,转换成具有较少的参数的函数的过程,具体将具有多个参数的函数转换成一系列嵌套函数,使用一部分参数调用柯里化函数返回一个新函数,每次返回的函数处理剩余的参数。
function multiply(a,b,c){
return a * b * c;
}
multiply(2,2,5)// 20
这个简单的函数定义了三个参数,参数相乘返回运算结果。
我们将上面的函数重构成柯里化结构的函数,用以说明柯里化的使用方法。
function multiply(a,b,c){
return a=> {
return b=> {
return c => {
return a * b * c;
}
}
}
}
multiply(2)(2)(5) // 20
通过柯里化函数,我们将一个功能改造成一系列的功能,将之前需要一次传递的多个参数,分为三次传递,每次传递的函数作为下一个函数的内链调用。
为了便于理解函数柯里化的调用,我们可以将上面的柯里化函数multiply(2)(2)(5) 调用过程分开书写。
const multiply_fir = multiply(2);
const multiply_sec = multiply_fir(2);
const result = multiply_sec(5);
console.log(result ); // 20
柯里化的应用
柯里化函数是函数式编程的一种很实用的实践。函数式编程是一种重要的编程范式,最重要的特点是函数作为第一等公民,并且强调函数本身的纯粹性,对于相同的输入参数返回相同的结果没有其他副作用。
所以我们创建的柯里化函数本身是一个纯函数,并且具有自己的特征,可以创建有意义的代码模块。
1. 代码的复用
当我们的函数参数大部分情况下相同的时候,我们可以利用柯里化解决公共参数复用的问题。
const obj = { name: 'test' };
const foo = function (prefix, suffix) {
console.log(prefix + this.name + suffix);
}.bind(obj, 'currying-');
foo('-function'); // currying-test-function
2. 函数的合成(Compose)
如果一个值要经过多个函数,才能变成另外一个值,就可以把所有中间步骤合并成一个函数,这叫做”函数的合成”(compose)
const compose = function (f, g) {
return function (x) {
return f(g(x));
};
}
3. 减少代码的中间变量
通过封装一系列处理步骤,可以减少对中间变量的操作,也是一种代码复用。比如我们需要操作一个数组,返回的对象是原数组每个元素上+1后的新的数组,这个需求很简单:
const list = [0, 1, 2, 3];
const list1 = list.map(elem => elem + 1); // => [1, 2, 3, 4]
当我们需求发生变化,需要增加+2的操作结果:
const list = [0, 1, 2, 3];
const list1 = list.map(elem => elem + 1); // => [1, 2, 3, 4]
const list2 = list.map(elem => elem + 2); // => [2, 3, 4, 5]
我们在维护这样一系列的代码的时候,很容易想到将list.map(elem => elem + 2)这样一个过程,进行封装,我们只需要传递我们需要操作的参数即可,这样可以提高代码的可读性。 我们的代码结构如下:
const plus1 = plus(1);
const plus2 = plus(2);
const list = [0, 1, 2, 3];
const list1 = list.map(plus1); // => [1, 2, 3, 4]
const list2 = list.map(plus2); // => [2, 3, 4, 5]
我们只需要实现plus()函数即可完成代码的封装,提高代码的维护性和可读性,JS柯里化可以实现我们的需求。
function plus(a) {
return function(b) {
return a + b;
}
}