您现在的位置是:亿华云 > 应用开发
前端进阶之认识与手写Compose方法
亿华云2025-10-02 18:41:52【应用开发】4人已围观
简介本文转载自微信公众号「前端阳光」,作者事业有成的张啦啦。转载本文请联系前端阳光公众号。事业有成的张啦啦前言:为什么要学习这个方法compose简介 compose的实现 最
本文转载自微信公众号「前端阳光」,前端作者事业有成的进阶张啦啦。转载本文请联系前端阳光公众号。识手事业有成的前端张啦啦
前言:为什么要学习这个方法
compose简介 compose的实现 最容易理解的实现方式 手写javascript中reduce方法 redux中compose的实现 参考文章前言:为什么要学习这个方法
遇到这个方法主要是最近在阅读redux,koa 原理 等多次遇到这个方法,进阶为了更好地理解框架原理,识手于是前端深入学习了一下compose的实现。
然后也发现这属于函数式编程的进阶东西,发现函数式编程是识手进击前端进阶的必经之路,因为像其中的前端纯函数的概念在redux的reducer中也展示得淋漓尽致,而保留函数计算结果的进阶思想无论是在vue,还是识手react等其他框架也多处见到。
所以建议有时间可以去看下函数试编程。前端
接下来,进阶就让我们学习下其中的识手compose函数吧!
compose简介
compose就是执行一系列的云南idc服务商任务(函数),比如有以下任务队列
let tasks = [step1, step2, step3, step4]每一个step都是一个步骤,按照步骤一步一步的执行到结尾,这就是一个compose
compose在函数式编程中是一个很重要的工具函数,在这里实现的compose有三点说明
第一个函数是多元的(接受多个参数),后面的函数都是单元的(接受一个参数) 执行顺序的自右向左的 所有函数的执行都是同步的还是用一个例子来说,比如有以下几个函数
let init = (...args) => args.reduce((ele1, ele2) => ele1 + ele2, 0) let step2 = (val) => val + 2 let step3 = (val) => val + 3 let step4 = (val) => val + 4这几个函数组成一个任务队列
steps = [step4, step3, step2, init]使用compose组合这个队列并执行
let composeFunc = compose(...steps) console.log(composeFunc(1, 2, 3))执行过程
6 -> 6 + 2 = 8 -> 8 + 3 = 11 -> 11 + 4 = 15所以流程就是从init自右到左依次执行,下一个任务的参数是上一个任务的返回结果,并且任务都是同步的,这样就能保证任务可以按照有序的源码库方向和有序的时间执行。
compose的实现
好了,我们现在已经知道compose是什么东西了,现在就来实现它吧!
最容易理解的实现方式
思路就是使用递归的过程思想,不断的检测队列中是否还有任务,如果有任务就执行,并把执行结果往后传递,这里是一个局部的思维,无法预知任务何时结束。直观上最容易理解。
const compose = function(...funcs) { let length = funcs.length let count = length - 1 let result return function f1 (...arg1) { result = funcs[count].apply(this, arg1) if (count <= 0) { count = length - 1 return result } count-- return f1.call(null, result) } }删繁就简来看下,去掉args1参数
const compose = function(...funcs) { let length = funcs.length let count = length - 1 let result return function f1 () { result = funcs[count]() if (count <= 0) { count = length - 1 return result } count-- return f1(result) } }这就好看很多,我们假设有三个方法,aa,bb,cc
function aa() { console.log(11); } function bb() { console.log(22); } function cc() { console.log(33); return 33 }然后传入compose
compose(aa,bb,cc)此时count = 2,则下面其实是执行cc
result = funcs[count]()然后count--。再递归执行f1,则下面其实就是执行bb
result = funcs[count]()这样,就实现了 从funcs数组里从右往左依次拿方法出来调用,再把返回值传递给下一个。高防服务器
后面的步骤同理。
这其实是一种面向过程的思想
手写javascript中reduce方法
为什么要手写?其实你要是能够很熟练的使用reduce,我觉得不必手写reduce,只是我觉得熟悉一下reduce内部的实现可以更好地理解后面的内容,况且 也不会太难呀!
function reduce(arr, cb, initialValue){ var num = initValue == undefined? num = arr[0]: initValue; var i = initValue == undefined? 1: 0 for (i; i< arr.length; i++){ num = cb(num,arr[i],i) } return num }如代码所示,就是先判断有没有传入初始值,有的话,下面的循环直接 从i = 0开始,否则i=1开始。
如果没有传入初始值,num就取 数组的第一个元素。这也是说明了为什么传入初始值,i就=1,因为第一个都被取出来了,就不能再取一次啦啦啦!
下面使用我们写的reduce方法
function fn(result, currentValue, index){ return result + currentValue } var arr = [2,3,4,5] var b = reduce(arr, fn,10) var c = reduce(arr, fn) console.log(b) // 24好了 ,没毛病,既然我们了解了reduce原理,就看看下面的redux中compose的实现吧
redux中compose的实现
function compose(...funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } debugger return funcs.reduce((a, b) => (...args) => a(b(...args))) }很简短,非常的巧妙,但是不是很不好理解。不过没关系。
依旧通过例子来讲解。
function aa() { console.log(11); } function bb() { console.log(22); } function cc() { 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
所以执行结果是
(...args) => dd(cc(...args))而dd(cc(...args))不就是先执行cc再执行dd吗?而dd就是执行bb再执行aa。
我的天,!这不是俄罗斯套娃吗!没错 redux中的compose的实现原理就是套娃哈哈哈!
参考文章
https://segmentfault.com/a/1190000011447164
很赞哦!(195)
相关文章
- 盘点那些常见的数据中心类型,你知道几个?
- 2、根据用户基础选择访问提供程序。由于互联问题的存在,接入商的选择也非常重要,如果用户群主要在联通,尽量选择联通接入较好的接入商,如果用户群主要在电信,那么选择电信接入较好的接入商。如果用户组位于国家/地区,则选择更好的访问提供程序进行交互。
- 2. 不要花大价钱买域名,新手鉴别能力不足,容易投资失误。
- 投资各类域名就像到处打游击战,结果处处失败。因为这样,对任何一个中国域名市场的走势和价格都没有准确的把握,所以最好缩小范围,准确把握战场态势,埋伏。
- 摩尔定律的终结对数据中心行业意味着什么?
- (4) 使用何种形式的域名后缀对网页搜索影响不大,但域名后缀也需要考虑方便用户记忆
- 投资各类域名就像到处打游击战,结果处处失败。因为这样,对任何一个中国域名市场的走势和价格都没有准确的把握,所以最好缩小范围,准确把握战场态势,埋伏。
- 互联网中的地址是数字的IP地址,域名解析的作用主要就是为了便于记忆。
- 记一次利用GrayLog实现采集与备份云服务器Web访问日志的实现过程
- a、变更前的公司证件扫描件(代码证或者营业执照)及联系人身份证复印件、变更后的公司证件扫描件(代码证或者营业执照)及新的联系人身份证复印件;身份证复印件需本人签名,公司证件复印件需加盖公章。
热门文章
站长推荐
介绍一套传统的日志监控服务器部署方案
4、说起来容易
4、说起来容易
2、定期提交和投标域名注册。例如,益华网络点击“立即预订”后,平台会抢先为客户注册域名。当然,一个域名可能会被多个客户预订,所以出价最高的人中标。
服务器内存故障预测居然可以这样做!
为了避免将来给我们的个人站长带来的麻烦,在选择域名后缀时,我们的站长最好省略不稳定的后缀域名,比如n,因为我们不知道策略什么时候会改变,更不用说我们将来是否还能控制这个域名了。因此,如果站长不是企业,或者有选择的话,如果不能选择域名的cn类,最好不要选择它。
4、待所有域名查询结束后可在右侧点击导出结果,即可以excel的文件方式将查询到的结果导出。
在更换域名后,并不是就万事大吉了,我们需要将旧域名做301重定向到新域名上,转移旧域名的权重到新域名上。