Redux源码分析之compose

时间:2020-12-06 01:39:15

Redux源码分析之基本概念

Redux源码分析之createStore

Redux源码分析之bindActionCreators

Redux源码分析之combineReducers

Redux源码分析之compose

Redux源码分析之applyMiddleware

   

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

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

  扩展运算符(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函数的入参,也就是 ...ag = fn3(...args)

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

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

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

引用:

redux middleware 详解