在 JavaScript 中,函数柯里化是函数式编程的重要思想,也是高阶函数中一个重要的应用,其含义是给函数分步传递参数,每次传递部分参数,并返回一个更具体的函数接收剩下的参数,这中间可嵌套多层这样的接收部分参数的函数,直至返回最后结果。
例如有一个简单的加法函数,他能够将自身的三个参数加起来并返回计算结果。
1 | function add(a, b, c) { |
那么add函数的柯里化函数_add则可以如下:
1 | function _add(a) { |
因此下面的运算方式是等价的。
1 | add(1, 2, 3); |
但是这样的函数扩展性差,只要参数个数超过3个就无法输出预期结果。
我们考虑使用链式调用的写法来解决这个问题,只要还有参数就一直返回函数自身:
1 | function add(x) { |
但是这样输出的结果并不是一个数字,而是一个函数对象的字符串表示。我们知道,当我们直接将函数参与其他的计算时,函数会默认调用toString方法,直接将函数体转换为字符串参与计算。因此我们可以重写toString方法。
1 | function add(x) { |
这样就能实现任意参数个数的加法了。但是如果想实现add(1,2)(3)这种形式去随意拆分参数呢?那我们可以用到ES6的扩展运算符来获取参数。
1 | function add(...args) { |
我们接下来封装一个通用的柯里化转换函数,可以将任意已知参数个数的函数转换成柯里化。
1 | function currying(func, args = []) { |
函数 currying 算是比较高级的转换柯里化的通用式,可以随意拆分参数,假设一个被转换的函数有多个形参,我们可以在任意环节传入任意个数的参数进行拆分,举一个例子,假如 5 个参数,第一次可以传入 2 个,第二次可以传入 1 个, 第三次可以传入剩下的,也有其他的多种传参和拆分方案,因为在 currying 内部收集参数的同时按照被转换函数的形参顺序进行了更正。