函数柯里化

774 阅读4分钟

前言

本文主要讲述函数柯里化的定义以及简单理解。

定义

维基百科中说:柯里化(Currying)是产生一系列连锁函数的一种方法,其中每个函数只有一个参数。借由另一个柯里化之后的新函数,传回其它剩余参数的功能。

举例

下面我们举一个简单的例子:

function curryingAdd(x) {
    return function add(y) {
        return x + y;
    };
};

console.log(curryingAdd(1)(3)); // 4

例子中我们看到,我们定义一个 curryingAdd 函数,在这个函数中返回了一个 add 函数,且这两个函数都只有一个形参。我们先调用 curryingAdd 函数,然后再调用生成的 add 函数,最终的结果 4 。其实我们还可以继续嵌套,形成一系列的函数,依次调用,最终得到结果。

那么我们为什么要这样做呢,我们直接传入两个参数,直接返回 x + y 不就好了吗,干嘛非要多加一层呢,这不是有点脱裤子放屁,多此一举吗?函数柯里化显然不是这样的花架子,要知道程序员都是一群十分 “懒惰” 的人,能少做绝不多做,不能少做创造条件也要少做,不但自己要少做,还想着让服务器,让客户端少做......

简单理解

上面的例子太过简单,无法体现柯里化的优点,我们再举下面这个例子:

function curryingIsHtmlTag(tags) {
    const tagArray = tags.split(',');
    return function isHtmlTag(tag) {
        return tagList.indexOf(tag) > -1;
    };
};

const tags = 'div,p,a,img,ul,li';

const isHtmlTag = curryingIsHtmlTag(tags)

console.log(isHtmlTag('div')); // true
console.log(isHtmlTag('template')); // false

在这个例子中,我们的 curryingIsHtmlTag 函数将我们传入的以 , 连接的 HTML 标签字符串转换为字符串数组,然后返回 isHtmlTag 函数,我们分别传入 divtemplate ,然后返回运算结果,分别是 true 和 false 。

你可能会问了,这又能说明什么呢?当考虑这个问题时,我们可以反过来思考,如果说不这样写会怎么样?

如果说我们不这样写的话,那么我们可以创建一个函数,传入tagstag ,在函数中我们将 tags 转换为字符串数组,然后再判断 tag 是否在数组中。当我们每次使用这个函数,都会执行一遍上面这个流程。注意,这里说的是每次,而关键就在于这个每次。

我们的 HTML 标签基本上来说极少需要去增加或者删除,所以我们每次调用函数, tagArray 都是相同的,既然是相同的我们显然就不应该去让他每次都运算一遍,而是想办法将其存起来。当我们将其存起来,首先,我们只需要获得一次 tagArray ,只要我们不是只调用一次,我们就减少了获取 tagArraay 的次数。其次,我们还可以提前调用 curryingIsHtmlTag 函数,然后当我们需要使用的时候,就可以直接调用 isHtmlTag 函数了。

什么?直接定义一个 tagArray 不就行了?这不是运算更少?对于这个问题我只能说我们这个例子还是过于简陋,拿一个最简单的需求来说,如果这里的 tags 不是 HTML 标签这种所有用户都是一样的。而是不同的用户有可能不一样,而对于同一个用户来说,它又是不变的。那么我们给就没法直接定义一个 tagArray ,因为我们肯定是不可能为不同的用户去 hard code 不同的数组的,我们就需要动态的为不同的用户创建不同的 tagArray,但是同一个用户,他的 tagArray 又是不变的,所以我们就可以通过柯里化来实现这样的需求。

function curryingRepayment (total) {
    return function repayment (once) {
        return total / once;
    };
};

let total = prompt('请输入你的房贷总额:');
const repayment = curryingRepayment(total); 

while (true) {
    let once = prompt('请输入你每个月的还款金额:');
    alert(`您共需还款${repayment(once)}次`);
}

比如上面这个悲伤的例子,不同的人的房贷总额是不同的,但是总额又是不变的。

好像我算的太简单了,我去哭一会......难受啊,马飞!!!!!!