函数柯里化的理解和实现

什么是柯里化?

在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,而且返回接受余下的参数并且返回结果的新函数的技术。

以上是维基百科对于柯里化给出的定义,总结一下:javascript

  • 输入是一个函数,而且这个函数拥有n个参数
  • 输出也是一个函数,而且能够使用fn()()()这种方式调用
  • 参数被柯里化过程当中的函数被拆分

写一个经典的用来解释柯里化的例子:java

function add(a, b, c) {
    return a + b + c;
}

const addTen = curry(add, 10); // curry就是后续咱们将实现的 柯里化函数
addTen(1)(2) // 13
addTen(3, 4) // 17

不难看出柯里化的用途之一就是参数复用,咱们能够经过柯里化的方式很方便的实现参数复用,可能这样你感受没啥卵用,再来看下面例子:数组

const amount = [
    { deposit: 120, finalPayment: 200 },
    { deposit: 110, finalPayment: 300 },
    { deposit: 130, finalPayment: 100 },
];

// 按照deposit的值对数组进行排序
// 很容易想到这么作
amount.slice().sort((a, b) => a.deposit - b.deposit);
// 后来又须要对finalPayment进行排序
amount.slice().sort((a, b) => a.finalPayment - b.finalPayment);

// 咱们再来使用柯里化的形式从新写一下
const sort = curry(function(field, a, b) {
    return a[field] - b[field];
})
console.log(amount.slice().sort(sort('deposit'))); // deposit进行排序
console.log(amount.slice().sort(sort('finalPayment'))); // finalPayment进行排序

简而言之:JavaScript中的柯里化实际上是利用闭包的特性,将全部参数都搜集到以后再一并执行。闭包

function fn(a, b, c, d, e...) {}
// 经过柯里化 转换为
curryFn(a)(b)(c)(d)(e)(...)

如何实现柯里化?

对于add(a, b) {}这样的函数咱们很容易柯里化它app

function add(a, b) {
    return a + b;
}

function curry(fn, a) {
    return function(b) {
        return fn(a, b);
    }
}

curry(add, 10)(1); // 11

没啥毛病,那我想作一个传入三个参数的函数柯里化咋办呢?安排~函数

function curry(fn, a) {
    return function(b) {
        return function(c) {
            return fn(a, b, c);
        }
    }
}

那四个参数咋办呢。。。很明显这种方式并不具有通用性,其实仔细观察上面的代码,仿佛,彷佛,可能递归能实现:this

function curry(fn, ...args) {
    return function(...innerArgs) {
        const allArgs = [...args, ...innerArgs];
        
        if (fn.length <= allArgs.length) {
            // 说明已经接受完全部参数,这个时候能够执行了
            return fn.apply(this, allArgs);
        } else {
            // 继续返回函数,收集参数
            return curry(fn, ...allArgs);
        }
    }
}

以上就是关于柯里化的知识,但愿对各位童鞋有所帮助。code

相关文章
相关标签/搜索