§ compose(…functions)

先说这个 API 的原因是它没有依赖,是一个纯函数

⊙ 源码分析

  1. /**
  2. * 看起来逼格很高,实际运用其实是这样子的:
  3. * compose(f, g, h)(...arg) => f(g(h(...args)))
  4. *
  5. * 值得注意的是,它用到了 reduceRight,因此执行顺序是从右到左
  6. *
  7. * @param {多个函数,用逗号隔开}
  8. * @return {函数}
  9. */
  10. export default function compose(...funcs) {
  11. if (funcs.length === 0) {
  12. return arg => arg
  13. }
  14. if (funcs.length === 1) {
  15. return funcs[0]
  16. }
  17. const last = funcs[funcs.length - 1]
  18. const rest = funcs.slice(0, -1)
  19. return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
  20. }

这里的关键点在于,reduceRight 可传入初始值:

  1. // 由于 reduce / reduceRight 仅仅是方向的不同,因此下面用 reduce 说明即可
  2. var arr = [1, 2, 3, 4, 5]
  3. var re1 = arr.reduce(function(total, i) {
  4. return total + i
  5. })
  6. console.log(re1) // 15
  7. var re2 = arr.reduce(function(total, i) {
  8. return total + i
  9. }, 100) // <---------------传入一个初始值
  10. console.log(re2) // 115

下面是 compose 的实例(在线演示):

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script src="//cdn.bootcss.com/redux/3.5.2/redux.min.js"></script>
  5. </head>
  6. <body>
  7. <script>
  8. function func1(num) {
  9. console.log('func1 获得参数 ' + num);
  10. return num + 1;
  11. }
  12. function func2(num) {
  13. console.log('func2 获得参数 ' + num);
  14. return num + 2;
  15. }
  16. function func3(num) {
  17. console.log('func3 获得参数 ' + num);
  18. return num + 3;
  19. }
  20. // 有点难看(如果函数名再长一点,那屏幕就不够宽了)
  21. var re1 = func3(func2(func1(0)));
  22. console.log('re1:' + re1);
  23. console.log('===============');
  24. // 很优雅
  25. var re2 = Redux.compose(func3, func2, func1)(0);
  26. console.log('re2:' + re2);
  27. </script>
  28. </body>
  29. </html>

控制台输出:

  1. func1 获得参数 0
  2. func2 获得参数 1
  3. func3 获得参数 3
  4. re16
  5. ===============
  6. func1 获得参数 0
  7. func2 获得参数 1
  8. func3 获得参数 3
  9. re26