柯里化

柯里化

引言

先说是啥,一般我们调用函数就是直接调用一次,然后就拿到返回结果,比如这样:

const add = (a, b) => a + b
const ans = add(1, 1)

但是有的时候,我们可能期望多次传入参数,这个函数能给我们缓存一下,最后传完的时候再返回结果,就像这样:

const curriedAdd = () => {
// TODO
}
const ans = curriedAdd(1)(1)

是啥

GPT 生成的:柯里化(Currying)是一种函数式编程的技术,它将接受多个参数的函数转换为一系列接受单个参数的函数。柯里化的主要作用是将函数变得更加灵活和模块化,使得函数的复用和组合更加容易。通过柯里化,我们可以将一个多参数的函数转换为一系列单参数的函数,这样可以更方便地进行函数的组合和部分应用。

简单说就是多参函数变成了单参,对于前面的一些复用的参数,不需要多次传入了,更加方便

实现

简单的

对于一开始的例子,可以写一个简单的版本,对于函数记忆参数,可以使用高阶函数+闭包来实现

const { log } = console
const add = (a, b) => a + b

const curryAdd = a => {
return b => a + b
}

log(add(1, 2))
log(curryAdd(1)(2))

那如果参数更多,数量也不确定的话,不能一层层嵌套下去吧?就得想想其他方法了。

复杂些

我们知道函数有 arguments 和 rest 参数,可以转成数组来处理,以及函数.length 可以获取到函数的参数数量

const { log } = console
const add = (a, b, c) => a + b + c

// curry是一个高阶函数,可以把fn转变成柯里化的函数
const curry = fn => {
// 返回的函数接受的参数是不固定的
const tempFn = (...rest) => {
// 当参数数量刚好满足fn就直接调用返回
if (rest.length >= fn.length) return fn(...rest)
// 参数数量还不够的时候就继续返回函数
else return (...newRest) => tempFn(...rest, ...newRest)
}
return tempFn
}

const curriedAdd = curry(add)
log(curriedAdd(1)(1)(2))
log(curriedAdd(1, 1)(2))

作用

  • 参数复用:比如 3 + 4,3 + 6,3 + 19,就可以基于 3 生成一个柯里化的函数,然后再把后面不同的参数传递给这一个函数。
  • 延迟执行:再没有传入所有参数的时候,函数没有被执行,可以缓存一下参数
  • 函数组合:可以把小函数组合成复杂函数,支持函数式编程

弊端

参数通过闭包保存,如果长时间不释放的话,可能造成内存泄漏,这个需要开发者正确使用,倒也不是他的问题了。