首页 > 代码库 > Redux源码分析之compose

Redux源码分析之compose

 Redux源码分析之基本概念 

Redux源码分析之createStore 

Redux源码分析之bindActionCreators 

Redux源码分析之combineReducers 

Redux源码分析之compose

   

 解读之前先了准备一下基本知识

  • rest参数

   形式为...变量名,用于获取函数的多余参数 ,该变量将多余的参数放入数组中, 只能是参数的最后一个。

  • 扩展运算符

   扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。      

var fun1 = (...args) => console.log(...args)
 fun1(1,‘Good‘)
// 结果输出 1, Good

 

 这是一个很重要的函数 compose, 其作用红色部分表达的很清楚。

其作用是把一系列的函数,组装生成一个新的函数,并且从后到前,后面参数的执行结果作为其前一个的参数。

/**
 * Composes single-argument functions from right to left. The rightmost
 * function can take multiple arguments as it provides the signature for
 * the resulting composite function.
 *
 * @param {...Function} funcs The functions to compose.
 * @returns {Function} A function obtained by composing the argument functions
 * from right to left. For example, compose(f, g, h) is identical to doing
 * (...args) => f(g(h(...args))).
 */

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }      

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

还是先来看一个简单的例子,结果上确实是如我们期望的。

var fn1 = val => ‘fn1-‘ + val
var fn2 = val => ‘fn2-‘ + val 
var fn3 = val => ‘fn3-‘ + val 

compose(fn1,fn2,fn3)(‘测试‘)

输出结果: fn1-fn2-fn3-测试

 我们回头看看最核心的一行代码。 

  return funcs.reduce((a, b) => (...args) => a(b(...args)))

  我们一步一步分解一下, func3 初始化的值为 funcs = [fn1,fn2,fn3], reduce执行

   第一步时 

  a = fn1

  b = fn2 

       a(b(...args)) = fn1(fn2(...args))

  (...args) => a(b(...args))   = (...args) = > fn1(fn2(...args))

  第二步时

      a =  (...ag) = > fn1(fn2(...ag))  // 避免和后面混淆,rest参数名修改为  ag

      b = fn3

      a(b(...args)) = a( fn3(...args) )  = fn1(fn2(    fn3(...args)   ))  // 这一步是关键,b(...args)执行后作为a函数的入参

   (...args) => a(b(...args))   = (...args) = > fn1(fn2(fn3(...args))) 

 

   所以最后返回的就是这样的一个函数  (...args) = > fn1(fn2(fn3(...args))) 

   再多函数,也是以此类推。  

 

引用:

redux middleware 详解

 

Redux源码分析之compose