前言
本文主要讲述函数柯里化的定义以及简单理解。
定义
维基百科中说:柯里化(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
函数,我们分别传入 div
与 template
,然后返回运算结果,分别是 true 和 false 。
你可能会问了,这又能说明什么呢?当考虑这个问题时,我们可以反过来思考,如果说不这样写会怎么样?
如果说我们不这样写的话,那么我们可以创建一个函数,传入tags
和 tag
,在函数中我们将 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)}次`);
}
比如上面这个悲伤的例子,不同的人的房贷总额是不同的,但是总额又是不变的。
好像我算的太简单了,我去哭一会......难受啊,马飞!!!!!!