js科里化
科里化定义如下: 首先将一批函数转入一个函数(然后这个函数返回一个新的函数),这中形式就叫“做科里化”(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);
});
js科里化的更多相关文章
- js currying & js 科里化
js currying & js 科里化 var test = ( function (a){ console.log(`a2 =`, a);// 1 // console.log(`b2 = ...
- groovy闭包科里化参数
科里化闭包:带有预先绑定形参的闭包.在预先绑定一个形参之后,调用闭包时就不必为这个形参提供实参了.有助于去掉方法调用中的冗余重复. 使用curry方法科里化任意多个参数 使用rcurry方法科里化后面 ...
- js柯里化的一个应用
听到同学说面试一道题目 add(1)(2)(3)(4); 查询了下资料 这是一个js里面的柯里化 现象 add_curry防范返回的是一个 retVal,并不是执行结果.这里的代码很想递归,但是不是 ...
- JS 柯里化 (curry)
用 JS 理解柯里化 函数式编程风格,试图以函数作为参数传递(回调)和无副作用的返回函数(修改程序的状态). 很多语言采用了这种编程风格.JavaScript,Haskell,Clojure,Erla ...
- js 柯里化Currying
今天读一篇博客的时候,看都有关柯里化的东西,由于好奇,特意查了一下,找到一篇比较好的文章,特意收藏. 引子先来看一道小问题:有人在群里出了到一道题目:var s = sum(1)(2)(3) .... ...
- JS - 柯里化
一:what's this? 柯里化: 是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术.其实,柯里化就是用闭包原理实现函数 ...
- js柯里化
这篇文章讲的很好啊~例子很好 http://www.zhangxinxu.com/wordpress/2013/02/js-currying/ 这篇是讲函数式编程的,其中也有涉及到,说明了柯里化是一种 ...
- js 柯里化、深拷贝、浅拷贝
curry const sum = (a, b, c, d) => a + b + c + d const curry = fn => (judge = (...args) => a ...
- laravel中closure和curry 科里化函数式编程
推荐值得的一看博客文档:谢谢作者 : https://my.oschina.net/zhmsong 函数式编程curry的概念: 只传递给函数一部分参数来调用函数,然后返回一个函数去处理剩下的参数. ...
随机推荐
- 【转】通过SQL Server 2008数据库复制实现数据库同步备份
SQL Server 2008数据库复制是通过发布/订阅的机制进行多台服务器之间的数据同步,我们把它用于数据库的同步备份.这里的同步备份指的是备份服务器与主服务器进行实时数据同步,正常情况下只使用主数 ...
- coursera 《现代操作系统》 -- 第四周 处理器调度
优先级反转 这往往出现在一个高优先级任务等待访问一个被低优先级任务正在使用的临界资源,从而阻塞了高优先级任务:同时,该低优先级任务被一个次高优先级的任务所抢先,从而无法及时地释放该临界资源.这种情况下 ...
- 疯狂创客圈 JAVA死磕系列 总目录
无编程不创客,无案例不学习.疯狂创客圈,一大波高手正在交流.学习中! 疯狂创客圈 Java 死磕系列: [博客园 总入口] QQ群:104131248 [Java 聊天室] 实战从0开始,打造100 ...
- jquery拓展插件-popup弹窗
css:<style> /* 公共弹出层 */ .popWrap{position: fixed;left: 0;top: 0; width: 100%;height: 100%;z-in ...
- 修改 /var/lib/locales/supported.d/local 文件(使用 locale -a 命令查看系统中所有已配置的 locale)
转自:http://zyxhome.org/wp/cc-prog-lang/c-stdlib-setlocale-usage-note/ http://www.west263.com/info/htm ...
- 022-Spring Boot 构建微服务实战
一.概述 二. 2.1.微服务 将原来一个大的系统,拆分成小系统 每个小系统分别开发,测试,维护 2.2.调用方 服务提供方式:rest(http)[restTemplate,httpclient]. ...
- Windows 上将Tomcat 8 安装为系统服务
第一部分 应用场景 需要服务器上Tomcat不显示启动窗口 需要服务器上Tomcat开机自启动 ... 第二部分 配置过程 一.修改配置文件 1 {Tomcat_HOME}/bin/service.b ...
- springMVC中使用 RequestBody 及 Ajax POST请求 415 (Unsupported Media Type)
使用POST请求的时候一直报错: Ajax 未设置 contentType 时会报 415 . 后台 RequestBody 承接前台参数,故对参数data的要求为“必传”“JSON”,否则会报40 ...
- 2015/7/29 (高开,V形反转,各种指标背离——可惜没买进,填补空缺图形的心理分析)
1.李大--謝先生℡:早盘决策:如今日再次出现大幅低开 或者盘中大幅下跌可逢低 3成仓位左右分散资金做短线抄底,切记是超短 绝不追高,设置5个点止损.市场有很多名家在谈论3373点即前低点,本人告诉 ...
- PsySH——PHP交互式控制台
PsySH PsySH is a runtime developer console, interactive debugger and REPL for PHP. PsySH是一个PHP的运行时开发 ...