持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
柯里化到底是什么
来看下维基百科的定义
维基百科: 在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
不理解吧,我们来举个简单的例子
function sum(m,n) {
return m+n
}
// 柯里化后
function sum (m) {
return function(n){
return m + n
}
}
在这个例子中实际上就是把sum函数的m,n两个参数,变成了先用一个函数接收m然后返回一个函数去处理n参数。这样看来,这个柯里化思路就比较清晰了,就是只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。
将以上求和函数柯里化得:
- 将传入的三个参数进行拆解,依次返回一个函数,并传入一个参数;
- 在保证同样功能的同时,其调用方式却发生了变化;
- 注意:在拆解参数时,不一定非要将参数拆成一个个的,也可以拆成2+1或1+2;
但是这个柯里化到底有什么用呢?我们需要把我们的方法这样改造成这样呢?
函数柯里化的特点及应用
- 让函数的职责更加单一 柯里化的函数,可以将函数的作用变的更加的单一,而不是将复杂的逻辑都交给一个函数来执行
举个例子,我们给上述的sum函数相加的结果,每次都加上2,分别来用两种方式写一下
普通方法
function sum(m,n) {
m = m+2
n= n+2
return m+n
}
柯里化后的函数
function sum(m) {
m = m+2
return function (n) {
n = n+2
return m+n
}
}
柯里化后,每个函数的参数所做的操作,更加的简洁了
- 可以使函数的参数得到复用 还是以上边的例子为例,现在想要固定第一个参数是100
普通方法
function sum(m,n) {
m = m + 2
n = n + 2
return m+n
}
let a = sum(100,10)
let b = sum(100,20)
let c = sum(100,20)
let d = sum(100,20)
let e = sum(100,11)
柯里化后
function sum (m) {
m = m + 2
return function (n) {
n = n + 2
return m+n
}
}
let sum100 = sum(100)
let a = sum100(5)
let b = sum100(10)
console.log(b) // 110
让我们来写一个函数来执行自动柯里化
搞清楚了柯里化的好处,我们就来写一个函数,怎么才能将一个普通的函数变成柯里化函数
// 自动柯里化
function criskaCurrying(fn) {
// 1. 拿到需要柯里化的函数的参数个数
let fnlength = fn.length
// 2.定义一个已经柯里化后的函数
function curreid(...args) {
// 2.1 拿到该函数参数的个数
let argslength = args.length
//2.2判断该函数传入参数的个数和fn参数个数进行比较
// 如果argslength >= fnlength, 则代表fn参数已经传入完毕,此时可以直接执行fn不需要再进行下一层的柯里化
if (argslength >= fnlength) {
// 2.2.1 直接执行fn,为了fn的this的指向的正确性,在执行前需要先进行显示绑定
// 换句话说。不能我fn函数穿进来,做了一次柯里化后得到的函数,无法进行再进行显示绑定吧
return fn.apply(this, args)
} else {
// 2.3 如果argslength < fnlength, 则代表fn参数没有传完,需要继续返回函数来执行参数
function curreid2(...args2) {
// 对参数进行合并
let sumargs = [...args, ...args2]
// 递归调用curreid,直到参数个数达到要求
return curreid.apply(this, sumargs)
}
// 返回继续接收参数函数
return curreid2
}
}
// 3.将柯里化的函数返回
return curreid
}
来个例子测试一下
// 测试
function sum(m,n,k){
return m+n+k
}
let sumCurrying = criskaCurrying(sum)
let a = sumCurrying(10)(10)(20)
let b = sumCurrying(10,20)(10)
let c = sumCurrying(10,10,20)
let d = sum(10,10,20)
console.log(a,b,c,d)
执行结果如下