实现函数fn,让其具有如下功能(百度二面)

  1. /*
  2. 在函数式编程当中有一个很重要的概念就是函数组合, 实际上就是把处理数据的函数像管道一样连接起来, 然后让数据穿过管道得到最终的结果。 例如:
  3. const add1 = (x) => x + 1;
  4. const mul3 = (x) => x * 3;
  5. const div2 = (x) => x / 2;
  6. div2(mul3(add1(add1(0)))); //=>3
  7. 而这样的写法可读性明显太差了,我们可以构建一个compose函数,它接受任意多个函数作为参数(这些函数都只接受一个参数),然后compose返回的也是一个函数,达到以下的效果:
  8. const operate = compose(div2, mul3, add1, add1)
  9. operate(0) //=>相当于div2(mul3(add1(add1(0))))
  10. operate(2) //=>相当于div2(mul3(add1(add1(2))))
  11. 简而言之:compose可以把类似于f(g(h(x)))这种写法简化成compose(f, g, h)(x),请你完成 compose函数的编写
  12. */

reduce 处理方式

  1. /**
  2. * 运用知识点:1)闭包作用域;2)柯里化思想(预先存储);
  3. * 执行compose函数,预先把要执行的函数存储起来,最后执行operate的时候把存储的值拿过来用,这还是柯里化思想。
  4. * 只不过在柯里化思想基础上,还做了函数嵌套等具体的处理。
  5. * compose组合函数
  6. **/
  7. const add1 = (x) => x + 1;
  8. const mul3 = (x) => x * 3;
  9. const div2 = (x) => x / 2;
  10. function compose(...funcs) {
  11. // funcs存储的是最后需要处理的函数集合
  12. return function operate(x) {
  13. // x存储初始第一个函数执行需要的实参
  14. if(funcs.length === 0) return x;
  15. if(funcs.length === 1) return funcs[0](x);
  16. // 把数据倒过来或者用reduceRight
  17. funcs.reverse();
  18. let firstFunc = funcs[0](x);
  19. funcs = funcs.slice(1);
  20. return funcs.reduce((result, item) => {
  21. return item(result);
  22. }, firstFunc)
  23. //funcs.reduceRight
  24. };
  25. };
  26. let operate = compose(div2, mul3, add1, add1);
  27. console.log(operate(0)); // => 3
  28. let operate = compose();
  29. console.log(operate(0)); // => 0
  30. let operate = compose(add1);
  31. console.log(operate(0)); // => 1
  1. const add1 = (x) => x + 1;
  2. const mul3 = (x) => x * 3;
  3. const div2 = (x) => x / 2;
  4. function compose(...funcs) {
  5. // funcs存储的是最后需要处理的函数集合
  6. return function operate(x) {
  7. // x存储初始第一个函数执行需要的实参
  8. if(funcs.length === 0) return x;
  9. if(funcs.length === 1) return funcs[0](x);
  10. // 把数据倒过来或者用reduceRight
  11. funcs.reverse();
  12. return funcs.reduce((result, item, index)=> {
  13. if(index===1) {
  14. return item(result(x));
  15. }
  16. return item(result)
  17. })
  18. };
  19. };
  20. let operate = compose(div2, mul3, add1, add1);
  21. console.log(operate(0)); // => 3
  22. let operate = compose();
  23. console.log(operate(0)); // => 0
  24. let operate = compose(add1);
  25. console.log(operate(0)); // => 1

image.png

  1. const add1 = (x) => x + 1;
  2. const mul3 = (x) => x * 3;
  3. const div2 = (x) => x / 2;
  4. function compose(...funcs) {
  5. // funcs存储的是最后需要处理的函数集合
  6. return function operate(x) {
  7. // x存储初始第一个函数执行需要的实参
  8. if(funcs.length === 0) return x;
  9. if(funcs.length === 1) return funcs[0](x);
  10. // 把数据倒过来或者用reduceRight
  11. funcs.reverse();
  12. let n = 0;
  13. return funcs.reduce((result, item)=> {
  14. if((++n)===1) {
  15. return item(result(x));
  16. }
  17. return item(result)
  18. })
  19. };
  20. };
  21. let operate = compose(div2, mul3, add1, add1);
  22. console.log(operate(0)); // => 3
  23. let operate = compose();
  24. console.log(operate(0)); // => 0
  25. let operate = compose(add1);
  26. console.log(operate(0)); // => 1
  1. const add1 = (x) => x + 1;
  2. const mul3 = (x) => x * 3;
  3. const div2 = (x) => x / 2;
  4. function compose(...funcs) {
  5. // funcs存储的是最后需要处理的函数集合
  6. return function operate(x) {
  7. // x存储初始第一个函数执行需要的实参
  8. if(funcs.length === 0) return x;
  9. if(funcs.length === 1) return funcs[0](x);
  10. // 把数据倒过来或者用reduceRight
  11. funcs.reverse();
  12. return funcs.reduce((result, item)=> {
  13. return item(result)
  14. }, x)
  15. };
  16. };
  17. let operate = compose(div2, mul3, add1, add1);
  18. console.log(operate(0)); // => 3
  19. let operate = compose();
  20. console.log(operate(0)); // => 0
  21. let operate = compose(add1);
  22. console.log(operate(0)); // => 1

redux源码中的compose处理方案

  1. const add1 = (x) => x + 1;
  2. const mul3 = (x) => x * 3;
  3. const div2 = (x) => x / 2;
  4. function compose(...funcs) {
  5. if(funcs.length === 0) {
  6. return arg => arg
  7. }
  8. if(funcs.length === 1) {
  9. return funcs[0]
  10. }
  11. // return funcs.reduce((a, b) => (...args) => a(b(...args)))
  12. return funcs.reduce((a, b) => {
  13. return (...args) => {
  14. // div2(mul3(add1(add1(0))))
  15. return a(b(...args))
  16. }
  17. })
  18. }
  19. let operate = compose(div2, mul3, add1, add1);
  20. console.log(operate(0)); // => 3