1. 概念
柯里化函数编程思想:Currying(柯里化)是将一个带有多个参数的函数转换为函数序列的过程,每个函数只有一个参数。
一个有n个参数的函数,可以使用柯里化将它变成一个一元函数。
const binaryFunction = (a, b) => a + b;
const curryUnaryFunction = a => b => a + b;
curryUnaryFunction(1); // returns a function: b => 1 + b
curryUnaryFunction(1)(2); // returns the number 3
柯里化函数非常适合提高代码的可重用性和函数式结构。
执行一个方法,传递一些参数进去,首先形成一个不销毁的私有作用域,把传递的这些值存储起来(没有立即使用,属于预先存储起来)
返回一个小函数给私有作用域外面的
当执行返回的小函数的时候,把之前第一步预先存储的信息拿过来使用(作用域链、闭包等机制完成的)
我们利用 JS 中基于闭包实现的预先存储的思想完成函数的柯里化。
2. 管道机制
在函数式编程中,有一个很重要的概念就是函数组合,实际上就是把处理数据的函数像管道一样连接起来,然后让数据穿过管道得到最终的结果。
const add1 = (x) => x + 1;
const mul3 = (x) => x * 3;
const div2 = (x) => x / 2;
div2(mul3(add1(add1(0)))) //=> 3
上面的写法可读性明显太差,我们可以构建一个 compose
函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后 compose
返回的也是一个函数,达到管道的效果。
const operate = compose(add1, add1, mul3, div2);
operate(0) //=> 3
compose
函数编写
//=> 字符串拼接成:div2(mul3(add1(add1(0)))) 这种形式,然后再使用 eval 执行它
const compose = (...funcs) => {
funcs = funcs.reverse();
return val => {
let str = '';
funcs.forEach((func) => {
str = str + func.name + ',';
});
str.replace(/,/g, '(');
str += val;
funcs.forEach(item => (str +=')'));
return eval(str);
}
}
//=> 利用数组的 forEach 方法,每次遍历之后让 val 赋值为上一次的执行结果
const compose = (...funcs) => {
return val => {
funcs.forEach(func=> {
val = func(val);
})
}
}
//=> 利用数组的 reduce 方法
const compose = (...arg) => {
return val => {
//=> 将 val 作为归并的初始值,a 为上一次函数执行的返回值,b 为当前项的值
arg.reduce((a, b) => {
return b(a);
}, val);
}
}
//=> 简化
const compose= (...funcs) =>
val => funcs.reduce((a, b) => b(a), val);