我们看过柯里化的概念就知道,柯里化是为了方便我们的函数使用把一个多参数的函数转化为单参数函数的方法。
帖大佬一个例子,很直观,重合部分的第三个参数我们可以通过volume柯里化避免重复传参。
然后下面是贴了一个柯里化的一般方法
curry函数是网上找的,我们先看用法
首先curry接受一个固定参数数量的函数
我试过了不固定参数长度是不行的会报错成xxx不是function,
但是只要固定了比如(x,y)=>x+y
有两个参数,那么我们的执行过程只要达到两个参数即f(1)(2)、f(1,2)、f()(1)(2)
的样子就可以返回curry里面函数的结果了(下面展开说一下)
中间还可以断开赋值一个函数体比如下面demo里面的m2
function curry (fn) {
const c = (...args) => (args.length === fn.length) ?
fn(...args) : (..._args) => c(...args, ..._args)
return c
}
var m=curry((x,y,z)=>console.log(x*y*z));
m(1)(3)(2);//6
var m2=m(1)(2);
m2(2);//4
var m3=m()(8,3)(1);
m3;//24
下面解释这个看起来很复杂的柯里化curry函数
首先以我们的m为例,
var m=curry((x,y,z)=>console.log(x*y*z));
传参 fn=(x,y,z)=>console.log(x*y*z)
虽然是个箭头函数,但是意思很明确啊,返回三者乘积
curry函数里面的固定变量c是返回值,那么我们看看这个c的样子
哇好长!!
c=()=>()?xx:xx
好了是个函数体无疑了(递归了还!!!)
fn.length
概念上是fn接收的参数的个数即curry里面那个函数的(x,y,z)
,然后(args.length === fn.length) ?
保证我们一定现有传参数达到函数接收的长度才行的
一开始args是执行部分第一个括号的内容,小于 fn.length
如果不等于会执行一个(..._args) => c(...args, ..._args)
即把下一次括号内的参数当成_args然后加到args中(这是个递归嵌套),最终都把参数整合到args数组
中
当执行到我们的传参数===需要参数的数目
的时候 return fn(...args)
此处的args是终极版!!
不过要小心如果执行过程中参数数量小于或大于
传参数则返回的是一个函数体而不是执行结果,小于的时候还好,我们可以继续加(),大于就看起来无能为力了。
稍微改一下 把===
改成>=
,可以简单保证不传多,假如手误多敲了一个他会按照前3个数去执行
(此处是一种隐式的函数解构
[x,y,z]=[...args]
根据函数规则如果args长度>3,x,y,z会只取前三个数
function curry (fn) {
const c = (...args) => (args.length >= fn.length) ?
fn(...args) : (..._args) => c(...args, ..._args)
return c
}
var m=curry((x,y,z)=>console.log(x*y*z));
m(1)(3)(2);//6
var m2=m(1)(2);
m2(2);//4
var m3=m()(8,3)(2,2,3);//24
m3;