什么是柯里化? 

  f(x)和g(x)合成为f(g(x)),有一个隐藏的前提,就是f和g都只能接受一个参数,如果可以接收多个参数,比如 f(x, y) 和 g(a, b, c),函数合成就非常麻烦了。 

  这时就需要使用到函数柯里化了,所谓的“柯里化”,就是把一个多参数的函数,转化为单参数函数。如下:



// 柯里化之前
function add(x, y) {
return x + y;
}

add(1, 2) // 3

// 柯里化之后
function addX(y) {
return function (x) {
return x + y;
};
}

addX(2)(1) // 3


   有了柯里化之后, 我们就能够做到,所有函数都只接受一个参数。 

 

 

   







 

 

  函数柯里化又称为部分求值,就是不会立即求值,而是等到了需要的时候再去求值。

 

  有这样的一个场景,记录程序员一个月的加班总时间,那么好,我们首先要做的就是记录程序员每天加班的时间,然后把一个月中每天加班的时间相加,这样,就得到了一个月的加班总时间。 

 


问题来了,我们又很多方法来实现,比如最简单的:



var monthTime = 0;
function overtime(time) {
return monthTime += time;
}

overtime(3.5); // 第一天
overtime(4.5); // 第二天
overtime(2.2); // 第三天
//...
//
//
//
overtime(3.2); // 第三十天

console.log(monthTime);


这个思路应该是最简单的,就是一个函数,变量时monthTime,每天加上加班小时数之后返回总的加班时间。   

每次传入加班时间都进行累加,这样当然没问题,但你知道,如果数据量很大的情况下,这样会大大牺牲性能。

 

那怎么办?这就是柯里化要解决的问题。

 

其实我们不必每天都计算加班时间只需要保存好每天的加班时间,在月底时计算这个月总共的加班时间,所以,其实只需要在月底计算一次就行

即对于每次输入的时间,我们只需要保存起来即可,这样,没有了加法返回的步骤,就可以减少运算了。 

如下所示的overtime函数还不是一个柯里化函数的完整实现,但是可以帮助我们了解其中的核心思想了:

这里的思想非常简单, 就是如果传入了参数,那么就把这个参数push到args数组中,表明这是在累加的阶段; 如果没有传入参数,那么就说明已经加完了,只要最后一次求和即可。  关键是这个overtime函数返回的是一个函数。  这里需要注意。如下:



var overtime = (function () {
var days = [];
return function () {
if (arguments.length == 1) {
[].push.apply(days, arguments);
} else {
var total = 0;
for (var i = 0; i < days.length; i++) {
total += days[i];
}
console.log(total);
return total;
}
}
})();


overtime(1);
overtime(2);
overtime(3);
overtime(4);
overtime(); // 10


即对于前面的四个overtime函数被调用的时候,其实只是保存了变量而已,并没有求值,直到最后才一起求值,这样有利于提高效率。