redux原理——ruduce函数和compose函数

8 篇文章 0 订阅

compose()合并函数核心:每次的返回值是一个函数,函数返回值作为下一个数组项函数的参数。

讲redux之前首先要理解一个函数-----reduce()

语法
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

参数说明:
一、function(total,currentValue, index,arr)	必需。用于执行每个数组元素的函数。
    函数参数:
    total	必需。初始值, 或者计算结束后的返回值。
    currentValue	必需。当前元素
    currentIndex	可选。当前元素的索引
    arr	可选。当前元素所属的数组对象。

二、initialValue	可选。传递给函数的初始值

reduce()函数有两种用法,一般我们只用到了第一种,即累加(这里不再举例)

   reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

还有一种比较高级的用法:

  reduce() 可以作为一个高阶函数,用于函数的 compose。

注:意思就是写个函数 能将多个函数进行组合成一个函数,就是一元链式函数

注意: reduce() 对于空数组是不会执行回调函数的。

例子:这里想到了数组的reduce()函数

实现思路:要想实现一个这样的函数,肯定是需要有一个遍历的过程,一个函数的执行结果是另一个函数的参数,那这样就需要有个累计的过程,综合以上2点,想到数组中有个reduce函数。这里我们来看看reduce函数

接下来实现:chained函数

function chained(funcs) {
  return function(input){
    return funcs.reduce(function(input, fn){ return fn(input) }, input);
  }
}

chained([f3,f2,f1])(2) //调用 

函数解析:分为以下4个步骤解析

chained函数入参funcs 函数数组  返回值:入参为input的函数(这里称为链式回调函数

链式回调函数:入参:input 初始值  返回值:reduce()函数 funcs 函数数组 执行reduce()函数

reduce函数:入参:计算函数和初始值

计算函数:function(input, fn){ return fn(input) }  

                  首次入参:input输入值  fancs数组的第一个元素 fn1

                  二次入参:fn1(input)执行后返回值  fancs数组的第一个元素 fn1

                  ...以此类推,知道fancs的数组元素全部参与执行

抽象理解:reduce 英文意思:减少;缩小

    A.reduce(function(total, currentValue, currentIndex, arr), initialValue) 可以理解为逐渐减少数组A的元素,减少执行该过程是传给回调函数,用作新的入参,而减少后变为回调函数的另一个入参(即total返回值)

数组A元素变化示意图:元素 ====> 入参 ====>返回值 ====> 入参 ====>……====>最终合成结果

——————————————————————————————————————————————————————

compose函数

基本语法:compose(fn1,fn2,fn3,fn4,...)

接收参数为函数,函数用逗号隔开,

返回值为:

function(){

      fn1(参数)  //这里的参数为执行fn2返回的结果

                       //特别注意fn2的入参f3的返回结果,依次类推

}

reduce函数执行:

reduce第一个入参:
function(a, b){
  return function(...args){
    return a(b(...args))
  }
}

第一次: a: fn1 b:fn2

第二次:a为上一次的返回值

a: function(){
  return fn1(fn2(...args)) //args是f3(...args)的返回结果
}

b: fn3

第三次:a为第二次函数返回结果

a: function(){
  return fn1(fn2(...args))  
}(fn3(...args)) //args是f4(...args)的返回结果

b: f4

第四次:a为第三次函数返回结果

a: function(){
  return function(){
    return fn1(fn2(...args))  
  }(fn3(...args)) 
}(fn4(...args))

函数源码参见:https://github.com/reduxjs/redux/blob/v3.7.2/src/compose.js

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) => b(a(...args)))  //从左到右
}

将上面的写法转换为es5:

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) => b(a(...args)))

  //下面函数是返回的compose函数
  return funcs.reduce(
    
    //下面返回函数是reduce的回调函数 接收 入参 a, b 
    //a为fn1 ,b为fn2(没有传入初始值)
    function(a,b){

      //下面返回函数是reduce的回调函数实际执行函数
      return function(...args){ //这里...args指的是compose函数传入的参数
         var transferVal = a(...args)
         return b(transferVal)
      }
    }
  )
}

chained([f3,f2,f1])(2) //调用

执行过程说明:

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

   第一步时 

  a = fn1

  b = fn2 

      ...args = 2

       b(a(2)) = fn2(fn1(2))

  (2) => b(a(2))   = (2) = > fn2(fn1(2))

第二步时

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

      b = fn3

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

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

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

reduce()合并函数核心:每次的返回值是一个函数,再用该函数去执行下一个数组元素(数组元素先执行传入参数返回)

说明:这里是从左到右

从右到左写为 funcs.reduce((a, b) => (...args) => a(b(...args)))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值