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的概念: 只传递给函数一部分参数来调用函数,然后返回一个函数去处理剩下的参数. ...
随机推荐
- C# Static修饰符的作用
MSDN上的定义 Use the static modifier to declare a static member, which belongs to the type itself rather ...
- HBase架构原理详情
本文从网上看到的,自己看过了,同时收藏下!感谢分享! HBase定义 HBase 是一个高可靠.高性能.面向列.可伸缩的分布式存储系统,利用Hbase技术可在廉价PC Server上搭建 大规模结构化 ...
- Xcode生成ipa文件
想到蒲公英应用做分发测试的同学们可以用的到哈 在测试的Device中切换为IOS Device,选择当前项目修改BuildSeting 在code signing Identity中选择证书,没有测试 ...
- 如何查看l操作系统是否开启rpc服务
linux操作系统 在linux 5.X以及下的版本你可以通过service portmap status命令查看rpc是否启动.如果提示running,表示正在运行:如果提示stop就是关闭了.如果 ...
- http-proxy-middleware使用方法和实现原理(源码解读)
本文主要讲http-proxy-middleware用法和实现原理. 一 简介 http-proxy-middleware用于后台将请求转发给其它服务器. 例如:我们当前主机A为http://loca ...
- Vue.js之组件传值
Vue.js之组件传值 属性传值可以从父组件到子组件,也可以从子组件到父组件. 这里讲一下从父组件到子组件的传值 还以上次的demo为例,demo里有APP.vue是父组件,Header.vue,Us ...
- 安装CentOS 7.4 可能会出现的坑以及解决方案
安装CentOS 7.4 可能会出现的坑以及解决方案 (解决方法不唯一,如果行不通的话emmmm~~, 百度会啥你会啥~~) 坑.0X01 解决: 退出虚拟机,以管理员权限运行 坑.0X02 解决: ...
- java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]
Links: 1.Getting availableProcessors is already set to [1], rejecting [1] IllegalStateException exce ...
- JavaScript实现自适应窗口大小的网页
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content ...
- 【转】Python爬虫_示例
爬虫项目:爬取汽车之家新闻资讯 # requests+Beautifulsoup爬取汽车之家新闻 import requests from bs4 import BeautifulSoup res ...