时间:2021-05-28
柯里化是干什么的?首先看看下面这个函数
let store = (a,b,c) => "这是你的七仔面" //函数就好像一个小卖部,一碗七仔面要三张软妹币:a,b,c (五个参数)那函数柯里化是什么?就是我们买面吃的过程可能是这样:
let curryStore = curry(store) //刚刚的小卖部被柯里化了//最佳状况curryStore(1,5,1)// 老板,刚好!不用找了,刚好七块钱。老板: "这是你的七仔面" //偶尔出现的情况let boss = curryStore(5) //老板,这五块钱你先拿着,我找找有没有一块钱。老板:……boss = boss(1) //有了老板,这一块钱你先拿着,我找找还有没有一块钱。。老板:……boss(1) //哈哈,终于找到了,给!老板:"这是你的七仔面" curryStore(5)(1)(1) //等价于上诉情况所以这里我们可以看到,函数柯里化,是可以用来慢慢凑齐参数,延迟函数的执行。(先分期交钱,后交货!)
做个题
现在,我们的目标是实现一个curry 函数,达到以下使用效果:
在给到足够的参数时,执行函数。不够参数的时候则返回一个新的curry函数。
作为一个js很厉害的人,这种问题用一行代码解决不是问题,问题是我没那么厉害。。。
于是,我们先从土方法说起吧orz
按照curry的用法,原理是返回了一个函数,这个函数的参数个数不确定(你可能同时掏出两张一块钱),于是我们可以运用不定参数的写法:
const curry = (fn) => { return (...args) =>{ //不定参数,想给多少给多少 //给钱交货环节 }}柯里化函数需要记住你已经给过他的参数,如果没给的话,则默认为一个空数组:
const curry = (fn,arr=[]) => { //arr数组用于记录已有参数 return (...args) =>{ //给钱交货环节 }}接下来每次调用的时候,需要检查参数是否给够,如果够了,则执行fn,没有的话则返回一个新的curry函数,将现有的参数塞给他:
const curry = ( fn, arr = []) => { return (...args) => { //判断参数总数是否和fn参数个数相等 if([...arr, ...args].length === fn.length){ return fn(...arr, ...args) //拓展参数,调用fn }else{ return curry(fn,[...arr, ...args]) //迭代,传入现有的所有参数 } }}到这里,其实我们已经实现了curry函数。
接下来就是要看看怎么写才能更简洁。
首先,中间的代码可以写成一个立即执行函数,省掉一些...arr, ...args:
if语句可以缩减成三元表达式,也可以省掉很多字啦:
const curry = ( fn, arr = []) => { return (...args) => { return ( a => { return a.length === fn.length ? fn(...a) : curry(fn, a) })([...arr, ...args]) }}最后,既然函数里啥事都没干,就只是return的话,不妨使用箭头函数最省的写法 input => output, 把return和大括号都给省了:
const curry = ( fn, arr = []) => { return (...args) => { return ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args]) //先折叠一层 }}再折叠:
const curry = ( fn, arr = []) => { return (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args]) //再折叠}收工了收工了:
const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args]) //衣服给您叠好了拿去试试:
const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args])let curryPlus = curry((a,b,c,d)=>a+b+c+d)curryPlus(1,2,3)(4) //返回10curryPlus(1,2)(4)(3) //返回10curryPlus(1,2)(3,4) //返回10当然了,柯里化函数的主要作用还是延迟执行,执行的触发条件不一定是参数个数相等,也可以是其他的条件,例如参数个为0的情况,那么我们需要对上面curry函数稍微做修改:
const curry = ( fn, arr = []) => (...args) => ( (a,b) => b.length === 0? fn(...a) : curry(fn, a))([...arr, ...args],[...args])let curryPlus = curry((...x)=>x.reduce((a,b)=>a+b))curryPlus(1) //返回一个函数curryPlus(1)(2) //返回一个函数//遇到参数个数为0的情况才执行curryPlus(1)(2)(4)() //返回7curryPlus(1,2)(4)() //返回7以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
关于async的介绍,在阮一峰的ES6入门教程中说到:async函数是什么?一句话,它就是Generator函数的语法糖。可是,为什么这么说呢?首先,比如说有一
以下内容通过代码讲解和实例分析了JS中精巧的自动柯里化实现方法,并分析了柯里化函数的基础用法和知识,学习一下吧。什么是柯里化?在计算机科学中,柯里化(Curry
本文实例讲述了js函数柯里化的方法和作用。分享给大家供大家参考,具体如下:函数柯里化的方法:1,利用数组的reduce方法可实现柯里化,具体参见我的另外一篇文章
本文实例讲述了es6函数之尾调用优化。分享给大家供大家参考,具体如下:什么是尾调用优化?尾调用是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指
概述在ES6前,实现模块化使用的是RequireJS或者seaJS(分别是基于AMD规范的模块化库,?和基于CMD规范的模块化库)。ES6引入了模块化,其设计思