ES6如何用一句代码实现函数的柯里化
柯里化是干什么的?首先看看下面这个函数
letstore=(a,b,c)=>"这是你的七仔面" //函数就好像一个小卖部,一碗七仔面要三张软妹币:a,b,c(五个参数)
那函数柯里化是什么?就是我们买面吃的过程可能是这样:
letcurryStore=curry(store)//刚刚的小卖部被柯里化了 //最佳状况 curryStore(1,5,1)//老板,刚好!不用找了,刚好七块钱。老板:"这是你的七仔面" //偶尔出现的情况 letboss=curryStore(5)//老板,这五块钱你先拿着,我找找有没有一块钱。老板:…… boss=boss(1)//有了老板,这一块钱你先拿着,我找找还有没有一块钱。。老板:…… boss(1)//哈哈,终于找到了,给!老板:"这是你的七仔面" curryStore(5)(1)(1)//等价于上诉情况
所以这里我们可以看到,函数柯里化,是可以用来慢慢凑齐参数,延迟函数的执行。(先分期交钱,后交货!)
做个题
现在,我们的目标是实现一个curry函数,达到以下使用效果:
在给到足够的参数时,执行函数。不够参数的时候则返回一个新的curry函数。
letcurryPlus=curry((a,b,c)=>a+b+c)//这里给到一个有三个参数的函数 curryPlus(1)(2)(3)//返回6 curryPlus(1)(2,3)//返回6 curryPlus(1,2)(3)//返回6 letx=curryPlus(1)(2)//喂,怎么才两个参数?返回一个curry函数(已经带了两个参数) x(1)//返回4 x(2)//返回5
作为一个js很厉害的人,这种问题用一行代码解决不是问题,问题是我没那么厉害。。。
于是,我们先从土方法说起吧orz
按照curry的用法,原理是返回了一个函数,这个函数的参数个数不确定(你可能同时掏出两张一块钱),于是我们可以运用不定参数的写法:
constcurry=(fn)=>{ return(...args)=>{//不定参数,想给多少给多少 //给钱交货环节 } }
柯里化函数需要记住你已经给过他的参数,如果没给的话,则默认为一个空数组:
constcurry=(fn,arr=[])=>{//arr数组用于记录已有参数 return(...args)=>{ //给钱交货环节 } }
接下来每次调用的时候,需要检查参数是否给够,如果够了,则执行fn,没有的话则返回一个新的curry函数,将现有的参数塞给他:
constcurry=(fn,arr=[])=>{ return(...args)=>{ //判断参数总数是否和fn参数个数相等 if([...arr,...args].length===fn.length){ returnfn(...arr,...args)//拓展参数,调用fn }else{ returncurry(fn,[...arr,...args])//迭代,传入现有的所有参数 } } }
到这里,其实我们已经实现了curry函数。
接下来就是要看看怎么写才能更简洁。
首先,中间的代码可以写成一个立即执行函数,省掉一些...arr,...args:
constcurry=(fn,arr=[])=>{ return(...args)=>{ return(a=>{//a是一个数组 if(a.length===fn.length){ returnfn(...a) }else{ returncurry(fn,a) } })([...arr,...args])//这里把arr和args摊开成一个数组赋值给a } }
if语句可以缩减成三元表达式,也可以省掉很多字啦:
constcurry=(fn,arr=[])=>{ return(...args)=>{ return(a=>{ returna.length===fn.length?fn(...a):curry(fn,a) })([...arr,...args]) } }
最后,既然函数里啥事都没干,就只是return的话,不妨使用箭头函数最省的写法input=>output,把return和大括号都给省了:
constcurry=(fn,arr=[])=>{ return(...args)=>{ return(a=>a.length===fn.length?fn(...a):curry(fn,a))([...arr,...args])//先折叠一层 } }
再折叠:
constcurry=(fn,arr=[])=>{ return(...args)=>(a=>a.length===fn.length?fn(...a):curry(fn,a))([...arr,...args])//再折叠 }
收工了收工了:
constcurry=(fn,arr=[])=>(...args)=>(a=>a.length===fn.length?fn(...a):curry(fn,a))([...arr,...args]) //衣服给您叠好了
拿去试试:
constcurry=(fn,arr=[])=>(...args)=>(a=>a.length===fn.length?fn(...a):curry(fn,a))([...arr,...args]) letcurryPlus=curry((a,b,c,d)=>a+b+c+d) curryPlus(1,2,3)(4)//返回10 curryPlus(1,2)(4)(3)//返回10 curryPlus(1,2)(3,4)//返回10
当然了,柯里化函数的主要作用还是延迟执行,执行的触发条件不一定是参数个数相等,也可以是其他的条件,例如参数个为0的情况,那么我们需要对上面curry函数稍微做修改:
constcurry=(fn,arr=[])=>(...args)=>((a,b)=>b.length===0?fn(...a):curry(fn,a))([...arr,...args],[...args]) letcurryPlus=curry((...x)=>x.reduce((a,b)=>a+b)) curryPlus(1)//返回一个函数 curryPlus(1)(2)//返回一个函数 //遇到参数个数为0的情况才执行 curryPlus(1)(2)(4)()//返回7 curryPlus(1,2)(4)()//返回7
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。