简单来讲,柯里函数就是只接受一个参数的函数,柯里化的起源请参看这篇文章:函数式编程入门教程
一般来说,若是三个数求和的函数咱们会这样写:javascript
function _sum3(x, y, z) { return x + y + z }
若是只考虑实现这个函数的柯里化,咱们能够这样作:html
function sum3(x) { return function(y) { return function(z) { return x + y + z } } } console.log(sum3(1)(2)(3)) // 6
观察上面两种不一样的写法能够发现,第二种写法其实就是首先把三个参数收集起来,而后到最后再调用第一种写法的函数:java
function sum3(x) { return function(y) { return function(z) { return _sum3(x, y, z) } } } console.log(sum3(1)(2)(3)) // 6
因此柯里化的写法只是把经常使用写法包装了一下,可使用一个专用的柯里化函数实现这种包装。柯里化函数是一种高阶函数,咱们把它命名为curryes6
function curry(fn) { return function(y) { return function(z) { return fn(x, y, z) } } } var sum3 = curry((x, y, z) => { return x + y + z }) console.log(sum3(1)(2)(3)) // 6
若是有要写一种更加通用的,能够柯里化拥有任意多个参数的函数呢,好比sumN(1)(2)(3)...(N),按照以前的写法,大概是这个样子的:编程
function curryN(fn) { return function(a1) { return function(a2) { return function(a3) { //...... return function(aN) { return fn(a1, a2, a3, ...aN) } } } } }
很容易想到能够用一个递归函数来简化这种写法,将上面那些看起来类似的函数结构命名为nest,就能够写为:数组
function nest(fn) { return function(x) { return nest(fn) } } function curry(fn) { nest(fn) }
这里缺乏一个循环终止的判断,因此nest函数先引入一个新参数i,当i === N时递归终止函数式编程
function nest(fn, i) { return function(x) { if (i === N) { return fn(...) } return nest(fn, i + 1) } } function curry(fn) { return nest(fn, 1) }
接着,须要一个存听任意多个参数的数组,将这个数组命名为args,而后传入nest函数函数
function nest(fn, i, args) { return function(x) { args.push(x) if (i === fn.length) { return fn(...args) } return nest(fn, i + 1, args) } } function curry(fn) { const args = [] return nest(fn, 1, args) }
最后在添加一个处理0个参数的状况,咱们就完成了最终版的柯里化函数测试
function curry(fn) { if (fn.length === 0) { return fn } const args = [] return nest(fn, 1, args) }
测试一下,在线demo:code
const log1 = curry((x) => console.log(x)) log1(10) // 10 const mul3 = curry((x, y, z) => console.log(x*y*z)) mul3(2)(3)(4) // 24