使用reduce实现pipe

本文摘要自修言的小册JavaScript 函数式编程实践指南

导语:我们都知道数组是可以链式调用的,像这样。

  const arr = [1, 2, 3]
	arr.map(mapArr).filter(filterArr).reduce(reduceArr)

那为什么数组可以实现链式调用,或者说满足什么条件才可以链式调用呢?

  • 它们都挂载在Array原型的Array.prototype上
  • 它们在结束之后都会返回新的Array
  • 既然return出来的也是Array,那么自然可以继续访问原型Array.prototype上的方法了。

综上所述,链式调用是有前提的。

它的本质是,是通过在方法中返回对象实例本身的 this/ 与实例 this 相同类型的对象,达到多次调用其原型(链)上方法的目的。

那我们在实际开发中,经常会遇到对数据进行复杂的处理,要经过好几个函数才可以处理完,就像这样:

function add4(num) {
  return num + 4
}  

function multiply3(num) {
  return num*3
}  

function divide2(num) {
  return num/2
}

以我们朴实无华的想法,应该怎样去写呢?

const sum =  add4(multiply3(divide2(num)))

3个处理看起来还可以,那如果多一点呢?

const sum =  square(minus10(computeWithBonus(add4(muliply3(divide2(num))))))

虽然我好像看到了我自己的代码,但是,家人们不重要,往下看….马上讲怎么摆脱回调地狱。

答案就是借助reduce实现pipe。(reduce不熟的记得先恶补之后再回来食用)

还是以上面的例子🌰。

reduce(callback,init)
function callback(pre,cur){}

其实就是把三个函数放在一个数组里,使用reduce,每次把计算出来的结果再作为下一个函数的参数,reduce第二个参数是

init也就是初始值,

第一次,pre就是初始值,也就是init的值,cur就是数组里的第一项;

第二次,pre是第一个函数计算出来之后的结果,cur是数组里的第二项;

第三次,pre是第二个函数计算出来之后的结果,cur是数组里的第三项;

返回计算之后的结果。

这个过程懂了,我们代码怎么实现呢?

funArr.reduce(callback, 0)
function callback(pre, cur) {
			return cur(pre)
		}

看起来也不难对吧,组合一下。

const pipe = funArr => {
		function callback(pre, cur) {
			return cur(pre)
		}
		return funArr.reduce(callback, 0)
	}
console.log(pipe([add4, multiply3, divide2]))

现在功能是实现了,我们不能每次都以0位初始值吧,我们需要动态的传参进去。

const pipe = (funArr) => {
		function funHandle(pre, cur) {
			return cur(pre)
		}
		return function (param) {
			return funArr.reduce(funHandle, param)
		}
	}
	const compose = pipe([add4, multiply3, divide2])
	console.log(compose(10))

怕小伙伴看不懂,我再详细的讲解一下这个方法。

const pipe = (funArr) => {
     console.log(1)
		function funHandle(pre, cur) {
			return cur(pre)
		}
		return function (param) {
			return funArr.reduce(funHandle, param)
		}
	}
    console.log(2)
	  const compose = pipe([add4, multiply3, divide2])
    console.log(3)
	  console.log(compose(10))

首先代码从上向下走,会走到console.log(2);

接着走到pipe([add4, multiply3, divide2]),这是对pipe的调用,所以对走进pipe方法里,执行

console.log(1),此时并不会执行return里面的内容,它只是返回了一个函数,但是并没有执行return里面的内容;

接着继续往下执行console.log(3),再执行 console.log(compose(10))compose = pipe

的返回值,所以compose(10)才是pipe返回的方法执行的时候。

最后,我们不去手动的拼凑数组,而是采用的形式,收集传参。

const pipe = (...funArr) => {
		function funHandle(pre, cur) {
			return cur(pre)
		}
		return function (param) {
			return funArr.reduce(funHandle, param)
		}
	}
	const compose = pipe(add4, multiply3, divide2)
	console.log(compose(10))

甚至你可以更加的精简

const pipe =
    (...funArr) =>
    param =>
        funArr.reduce((pre, cur) => cur(pre), param)

上面就是使用reduce实现pipe的全过程了,那Compose怎么实现呢?

就是reduce倒过来实现。

function compose(...funcs) {
  function callback(input, func) {
    return func(input)
  }  

  return function(param) {
    return funcs.reduceRight(callback,param)
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值