函数柯里化思想
预先存储(预处理),利用闭包的“保存机制”,我们把一些值事先存储起来,供其下级上下文中后期使用
例:(百度的一道面试题)
实现函数,让其具有如下功能
let res = fn(1,2)(3);
console.log(res); //=>6 1+2+3
答:
const fn = (...params) => {
return (...args) => {
params = params.concat(args);
return params.reduce((result, item) => result + item);
};
};
let res = fn(1, 2)(3);
console.log(res); //=>6 1+2+3
加强版:如果不知道函数执行的次数呢?
答:
// 基于console.log或者alert输出一个函数,会默认先把函数转化为字符串「Symbol.toPrimitive -> valueOf -> toString」,然后再输出「只不过浏览器为了让开发者知道这是个函数字符串,所以在输出的字符串前面,加了一个“f”」
const curring = function curring() {
let params = [];
const add = (...args) => {
// 把每一次ADD执行传递的实参拼接到PARAMS中
params = params.concat(args);
return add;
};
// 重写ADD的Symbol.toPrimitive,实现输出ADD函数的时候,把之前PARAMS中存储的值求和
add[Symbol.toPrimitive] = function toPrimitive() {
return params.reduce((result, item) => result + item);
};
return add;
};
let add = curring();
let res = add(1)(2)(3);
console.log(res); //->6
add = curring();
res = add(1, 2, 3)(4);
console.log(res); //->10
add = curring();
res = add(1)(2)(3)(4)(5);
console.log(res); //->15
管道函数
在函数式编程当中有一个很重要的概念就是函数组合, 实际上就是把处理数据的函数像管道一样连接起来, 然后让数据穿过管道得到最终的结果。 例如:
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(div2, mul3, add1, add1)
operate(0) //=>相当于div2(mul3(add1(add1(0))))
operate(2) //=>相当于div2(mul3(add1(add1(2))))
简而言之:compose可以把类似于f(g(h(x)))这种写法简化成compose(f, g, h)(x),请你完成 compose函数的编写
const add1 = x => x + 1;
const mul3 = x => x * 3;
const div2 = x => x / 2;
const compose = function compose(...funcs) {
let len = funcs.length;
if (len === 0) return x => x;
if (len === 1) return funcs[0];
return function operate(x) {
return funcs.reduceRight((result, func) => {
return func(result);
}, x);
};
};
const operate = compose(div2, mul3, add1, add1);
console.log(operate(0));