柯里化

288 阅读4分钟

柯里化这个东西怎么说呢,看名字就感觉很玄乎,我也看了很多讲柯里化的资料,真是越看越迷糊。于是乎我的牛脾气就上来了,要是不把这个整明白我就不姓牛(反正我本来也不姓牛),在我查阅了众多资料后,结合自己的理解,呕心沥血写下这篇文章,希望能帮助到跟我一样可爱的童鞋们~~~

首先,根据惯例,不懂的东西就要问问万能的度娘,所以我就百度了一下“柯里化”,然后看大了维基百科给出的解释:


excuse me?这是绕口令吗,我可能是语文没学好,看不太明白······

于是,我又查,这次在某博客里面看到一个容易懂一点的说法:

柯里化其实是函数式编程的一个过程,在这个过程中我们能把一个带有多个参数的函数转换成一系列的嵌套函数。它返回一个新函数,这个新函数期望传入下一个参数。

现在,根据上面的两种说法,我们能知道四个信息:

1、这是一个嵌套函数

2、这个函数能接收多个参数

3、返回一个新函数

4、柯里化的作用是把接受多个参数的函数转化为接收一个函数的参数

那么,这些东西怎么连贯起来呢,继续看

在《Mostly adequate guide》一书中,这样总结了 Currying ——只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数

这次,我们又可以多看出点东西:

柯里化怎么让只接收一个参数的函数处理多个参数的呢?原来是让返回的新函数处理剩下的参数。

现在我们来看个例子:

// 柯里化拆分
// 原函数
function add(a, b, c) {
    return a + b + c;
}

// 柯里化函数
function addCurrying(a) {
    return function (b) {
        return function (c) {
            return a + b + c;
        }
    }
}

// 调用原函数
add(1, 2, 3); // 6

// 调用柯里化函数
addCurrying(1)(2)(3) // 6

这个就是最基本的柯里化。但这个是需要改进的。

现在来总结一下柯里化的概念:柯里化是指这样一个函数(假设叫做Curry),他接收函数F作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数F的剩余参数。

上面的柯里化函数没涉及到高阶函数,也不具备通用性,无法转换形参个数任意或未知的函数。柯里化函数的运行过程其实是一个参数的收集过程,将每一次传入的参数收集起来,并在最里层里面处理。

我们接下来封装一个通用的柯里化转换函数,可以将任意函数转换成柯里化。

    var curry = function(fn) {
         var limit = fn.length
         return function judgeCurry (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {
                     return judgeCurry.apply(null, args.concat(args2))                                     
                 }
             }
         }
    }

这个currying函数的封装借助闭包与递归,实现了一个参数收集,并在收集完毕之后执行所有参数的一个过程。

也许大家很不解,为什么明明简单的操作要用柯里化整的这么花里胡哨呢?

柯里化确实是把简答的问题复杂化了,但是复杂化的同时,我们使用函数拥有了更加多的自由度。柯里化的核心正是对于函数参数的自由处理。

虽然柯里化确实在一定程度上将问题复杂化了,也让代码更加不容易理解,但是柯里化在面对复杂情况下的灵活性却让我们不得不爱。

在我们的实际开发中,如果我们遇到了普通封装无法实现的功能时,可以尝试柯里化,会有惊喜的哟!

但是,柯里化通用式里调用了arguments对象,使用了递归与闭包,因此柯里化的自由度是以牺牲了一定的性能为代价换来的。只有在情况很复杂的时候,柯里化才真的是有意义的,否则可能会得不偿失。

推荐一篇讲柯里化的文章:segmentfault.com/a/119000000…

结语

文章主要讲了一下柯里化的概念,关于实例部分说的比较少,因为普通函数用柯里化实在有点鸡肋,不但没必要,反而让大家觉得用了反而更复杂,所以还是等有缘遇上复杂的案例再来补充吧,大家理解柯里化的思想就好。希望能帮到大家~~~