当前位置: 首页 > 科技观察

前端进阶理解与手写撰写方法

时间:2023-03-13 21:04:48 科技观察

本文转载自微信公众号“前端阳光”,作者张拉拉,事业有成。转载本文请联系前方阳光公众号。事业有成的张拉拉前言:我为什么要学这个方法?最近在看redux、koa原理等的时候多次遇到这种方法,为了更好的理解框架原理,深入研究了compose的实现。然后我也发现这属于函数式编程,发现函数式编程是攻击高级前端的必经之路,因为像它这样的纯函数的概念在redux的reducer中也表现的淋漓尽致,而函数计算结果被保留。很多地方都可以看到idea,不管是vue还是react等框架。所以建议大家有空可以看看函数试用编程。接下来,让我们了解一下compose函数吧!compose简介Compose就是执行一系列的任务(函数),比如下面的任务队列lettasks=[step1,step2,step3,step4]每一步都是一个step,按照step一步步执行到最后。这是一个组合。Compose是函数式编程中一个非常重要的工具函数。这里实现的compose有三点说明,第一个函数是multivariate(接受多个参数),后面的函数都是unit(接受一个参数),执行顺序是从右到左。所有的功能都是同步执行的。或者举个例子,比如有如下函数letinit=(...args)=>args.reduce((ele1,ele2)=>ele1+ele2,0)letstep2=(val)=>val+2letstep3=(val)=>val+3letstep4=(val)=>val+4个函数一个任务队列steps=[step4,step3,step2,init]用compose组合这个队列,执行letcomposeFunc=compose(...steps)console.log(composeFunc(1,2,3))执行流程6->6+2=8->8+3=11->11+4=15所以流程是从init开始从右往左执行的,下一个任务的参数是上一个任务的返回结果,并且任务都是同步的,所以可以保证任务能够在有序的方向和有序的时间内执行。compose实现完成,我们现在知道什么是compose了,现在就来实现吧!理解实现方法最简单的方法就是用递归过程的思想,不断检测队列中是否有任务,如果有任务就执行,后面传递执行结果。这里是片面的思考,无法预测任务什么时候结束。直观上最容易理解。constcompose=function(...funcs){letlength=funcs.lengthletcount=length-1letresultreturnfunctionf1(...arg1){result=funcs[count].apply(this,arg1)if(count<=0){count=length-1returnresult}count--returnf1.call(null,result)}}简单看一下,去掉args1参数constcompose=function(...funcs){letlength=funcs.lengthletcount=length-1letresultreturnfunctionf1(){result=funcs[count]()if(count<=0){count=length-1returnresult}count--returnf1(result)}}这样看起来好多了,我们假设有三个方法,aa,bb,ccfunctionaa(){console.log(11);}functionbb(){console.log(22);}functioncc(){console.log(33);return33}然后此时传入composecompose(aa,bb,cc)count=2,那么下面其实就是Executeccresult=funcs[count]()然后count--。然后递归执行f1,那么下面其实就是执行bbresult=funcs[count](),实现了从funcs数组从右到左调用方法,然后将返回值传递给下一个。以下步骤相同。这其实是一种面向过程的思想。为什么需要手写javascript写reduce方法?其实如果能熟练使用reduce,我觉得没必要手写reduce。我只是觉得熟悉reduce的内部实现可以更好的理解下面的内容。有内容,也不会太难!functionreduce(arr,cb,initialValue){varnum=initValue==undefined?num=arr[0]:initValue;vari=initValue==undefined?1:0for(i;iarg}if(funcs.length===1){returnfuncs[0]}debuggerreturnfuncs.reduce((a,b)=>(...args)=>a(b(...args)))}简洁明了,但不是很难理解。但没关系。还是通过例子来解释。functionaa(){console.log(11);}functionbb(){console.log(22);}functioncc(){console.log(33);}假设只有这三个方法,我们如何先执行cc然后执行bb,然后执行aa?没错,直接写aa(bb(cc()))就可以了。非常巧妙。它不仅完成了执行序列,还实现了将上一个方法执行返回的结果传递给下一个方法。要执行的方法。下面这段代码所做的是将funcs数组[aa,bb,cc]转换为aa(bb(cc()))funcs.reduce((a,b)=>(...args)=>如何a(b(...args)))会这样做吗?看下面的解释:reduce内部第一次执行返回的结果是一个方法(...args)=>aa(bb(...args))现在我们把这个方法简化为dd,即当dd=(...args)=>aa(bb(...args))在reduce内部第二次执行,此时的a是上次返回的dd方法,b是cc,所以执行resultis(...args)=>dd(cc(...args))anddd(cc(...args))是不是先执行cc再执行dd?而dd就是先执行bb再执行aa。我的上帝!这不是俄罗斯套娃吗?没错,redux中compose的实现原理就是套娃哈哈哈!参考文章https://segmentfault.com/a/1190000011447164