科里化定义如下: 首先将一批函数转入一个函数(然后这个函数返回一个新的函数),这中形式就叫“做科里化”(currying)

Function.prototype.curry = function(){
var fn = this, // 这里就是在预装参数,将参数抓住,缓存在变量args中
args = Array.prototype.slice.call(arguments);
return function(){
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)))
};
}; String.prototype.csv = String.prototype.split.curry(/,\s*/);
var results = ("Mugan, Jin, Fuu").csv(); console.log(results[0],results[1],results[2]);

上面这个例子看懂了吗?

curry这个函数做的事情,是将函数中的this和arguments缓存在了闭包之中。

当split函数调用curry的时候,curry中的this就是split函数本身, 正则表达式这个参数则是预存在curyry中的arguments。

虽然这段代码实现已经很不错了,但是我们还可以进行一些改进。 上面这个curry函数,实现了将所有参数缓存在闭包之中。 当调用闭包返回的新的函数的时候才去处理之前预装的所有参数。

但是如果我不想让所有的参数全部预装,而是只预装其中一部分, 另外一部分参数要在调用闭包返回的那个新的函数中,将这部分参数传入。

Function.prototype.partial = function(){
var fn = this, args = Array.prototype.slice.call(arguments);
return function(){
var arg = 0;
for (var i = 0; i < args.length && arg < arguments.length; i++){
if (args[i] === undefined){
args[i] = arguments[arg++];
}
}
return fn.apply(this, args);
};
}; var delay = setTimeout.partial(undefined, 10);
delay(function(){
alert(true);
}); var bindClick = document.body.addEventListener.partial("click", undefined, false);
bindClick(function(){
alert(true);
});

partial()的实现和curry()有些相像。 在第一批的参数中,我们用undefined代表了那部分缺省参数。 在后面delay调用的时候,才将真正想要被处理的参数传递进去。

再来看一道面试题:

var fn = function(a,b,c){
    return a+b+c;
}

需要写一个函数,满足curry(fn)(1)(2)(3) //6

var curry = function(fn){
//参数集合
var args = [];
//函数的形参个数
var fnLen = fn.length; return function(){
//合并参数
args = args.concat([].slice.call(arguments));
//返回函数自身
if(args.length < fnLen) return arguments.callee;
//执行函数并返回结果
return fn.apply(this,args);
};
}; var fn=function(a,b,c){
return a+b+c;
}; var c = curry(fn)(1)(2)(3);
alert(c); //

用AOP装饰函数

首先给出Function.prototype.before方法和Function.prototype.after方法:

Function.prototype.before = function(beforefn){
var _self = this; //保存原函数的引用
return function(){ //返回包含了原函数和新函数的“代理”函数
beforefn.apply(this,arguments); //执行新函数,且保证this不被劫持,新函数接受的参数
//也会被原封不动地传入原函数,新函数在原函数之前执行
return _self.apply(this,arguments); //执行原函数并返回原函数的执行结果,并且保证this不被劫持
}
};
Function.prototype.after = function(afterfn){
var _self = this;
return function(){
var ret = _self.apply(this,arguments);
afterfn.apply(this,arguments);
return ret;
}
};

Function.prototype.before接受一个函数当作参数,这个函数即为新添加的函数,它装载了新添加的功能代码。

接下
来把当前的this保存起来,这个this指向原函数,然后返回一个“代理”函数,这个“代理”函数只是结构上像代理而已,并不承担代理的职责(比如控制
对象的访问等)。它的工作是把请求分别转发给新添加的函数和原函数,且负责保证它们的执行顺序,让新添加的函数在原函数之前执行(前置装饰),这样就实现
了动态装饰的效果。

我们注意到,通过Function.prototype.after的原理跟Function.prototype.before一模一样,唯一不同的地方在于让新添加的函数在原函数执行之后再执行。

用Function.prototype.before来增加新的window.onload事件是多么简单:

window.onload = function(){
console.log(1);
} window.onload = (window.onload || function(){}).after(function(){
console.log(2);
}).after(function(){
console.log(3);
}).after(function(){
console.log(4);
});

最新文章

  1. UVA227
  2. dyld: Library not loaded: @rpath/libswiftCore.dylib 解决方法
  3. The Simplified Project Management Process
  4. Mongodb的索引--学习笔记(未完)
  5. 【原创】微信公众号与HTML 5混合模式揭秘3——JSSDK获取地理位置
  6. MySQL partition分区I
  7. [wikioi]多源最短路
  8. MySQL协议简单分析
  9. css.day02.eg
  10. 一个简单链表的C++实现
  11. CentOS7.2上用KVM安装虚拟机window10踩过的坑
  12. sqli-libs
  13. vue中提示$index is not defined
  14. python习题实例(上)_update18/07/03
  15. 初始化 CSS 样式
  16. mybatis教程2(配置文件)
  17. learning at command AT+CEREG
  18. 监控hdfs 块迁移数量脚本及 metasave 日志内容详解
  19. Alpha阶段scrum meeting七天冲刺博客-天冷记得穿秋裤队
  20. javascript Object.create()究竟发生了什么

热门文章

  1. Intellij IDEA工具的常用快捷键
  2. 2018.10.24-day3 python总结
  3. Constructor Acquires, Destructor Releases Resource Acquisition Is Initialization
  4. (1)虚拟机的安装与使用,linux系统安装
  5. github常用的git命令
  6. 如何高效地分析Android_log中的问题?——查看Android源码
  7. 3.4 使用STC89C52控制MC20解析GPS的经纬度数据在LCD1602上显示
  8. Python之匿名函数(Day18)
  9. 希望and目标
  10. spark学习(2)--hadoop安装、配置