就像最先听到斐波拉切数列同样,第一次听到柯里化我也是懵逼的javascript
本文旨在让你们简单理解柯里化和反柯里化,这里不作深刻探究,只求能带你们装逼就好,看完还不懂你砍我。github
咱们先来简单了解一下他们的做用。设计模式
柯里化又称部分求值,字面意思就是不会马上求值,而是到了须要的时候再去求值。若是看的懵逼,没事,看完整篇文章再回过头来看这里你就会豁然开朗。微信
反柯里化的做用是,当咱们调用某个方法,不用考虑这个对象在被设计时,是否拥有这个方法,只要这个方法适用于它,咱们就能够对这个对象使用它。app
咱们有这样一个场景,记录程序员一个月的加班总时间,那么好,咱们首先要作的是记录程序员天天加班的时间,而后把一个月中天天的加班的时间相加,就获得了一个月的加班总时间。函数
但问题来了,咱们有不少种方法能够实现它,好比最简单的:性能
var monthTime = 0;
function overtime(time) {
return monthTime += time;
}
overtime(3.5); // 第一天
overtime(4.5); // 次日
overtime(2.1); // 第三天
//...
console.log(monthTime); // 10.1复制代码
每次传入加班时间都进行累加,这样固然没问题,但你知道,若是数据量很大的状况下,这样会大大牺牲性能。
那怎么办?这就是柯里化要解决的问题。
其实咱们没必要天天都计算加班时间,只须要保存好天天的加班时间,在月底时计算这个月总共的加班时间,因此,其实只须要在月底计算一次就行。
下面的overtime函数还不是一个柯里化函数的完整实现,但能够帮助咱们了解其核心思想:
var overtime = (function() {
var args = [];
return function() {
if(arguments.length === 0) {
var time = 0;
for (var i = 0, l = args.length; i < l; i++) {
time += args[i];
}
return time;
}else {
[].push.apply(args, arguments);
}
}
})();
overtime(3.5); // 第一天
overtime(4.5); // 次日
overtime(2.1); // 第三天
//...
console.log( overtime() ); // 10.1复制代码
柯里化的核心思想就是这样,看到这里你确定已经懂了,至于真正的柯里化函数,网上有不少,你们能够去Google一下。
反柯里化的的做用已经在前言说过了,这里讲下它的由来。
2011年JavaScript之父Brendan Eich发表了一篇Twitter,提出了反柯里化这个思想,下面这段代码是反柯里化的实现方式之一:
Function.prototype.uncurring = function() {
var self = this;
return function() {
var obj = Array.prototype.shift.call(arguments);
return self.apply(obj, arguments);
};
};复制代码
咱们先来看看上面这段代码有什么做用。
咱们要把Array.prototype.push方法转换成一个通用的push函数,只须要这样作:
var push = Array.prototype.push.uncurring();
//测试一下
(function() {
push(arguments, 4);
console.log(arguments); //[1, 2, 3, 4]
})(1, 2, 3)复制代码
arguments
原本是没有push
方法的,一般,咱们都须要用Array.prototype.push.call
来实现push
方法,但如今,直接调用push
函数,既简洁又意图明了。
就和前言写的那样,咱们不用考虑对象是否拥有这个方法,只要它适用于这个方法,那就可使用这个方法(相似于鸭子类型)。
咱们来分析一下调用Array.prototype.push.uncurring()
这句代码时,发生了什么事情:
Function.prototype.uncurring = function() {
var self = this; //self此时是Array.prototype.push
return function() {
var obj = Array.prototype.shift.call(arguments);
//obj 是{
// "length": 1,
// "0": 1
//}
//arguments的第一个对象被截去(也就是调用push方法的对象),剩下[2]
return self.apply(obj, arguments);
//至关于Array.prototype.push.apply(obj, 2);
};
};
//测试一下
var push = Array.prototype.push.uncurring();
var obj = {
"length": 1,
"0" : 1
};
push(obj, 2);
console.log( obj ); //{0: 1,1: 2, length: 2 }复制代码
看到这里你应该对柯里化和反柯里化有了一个初步的认识了,但要熟练的运用在开发中,还须要咱们更深刻的去了解它们内在的含义。
喜欢本文的朋友能够关注个人微信公众号,不按期推送一些好文。
本文出自Rockjins Blog,转载请与做者联系。不然将追究法律责任。