//反科里化
Function.prototype.uncurrying = function() {
var _this = this;
return function() {
return Function.prototype.call.apply(_this, arguments);
//_this.call(arguments);
//在下面的例子中Array.prototype.push == _this
//因为call 本身也是个函数
//Function.prototype.call.apply 就是去调用call()方法
//也就是Array.prototype.push.call(arguments);
//arguments 也就是 return function()中传入的参数组
//例子中push(arr,"a") arguments 就是[arr,"a"];
//apply第二个参数接受数组,arguments 是伪数组(Object 类型).
//call 接受参数序列 arg1, arg2, , argN ,arguments 会被转化成 arr , "a"
//所以实际上到最后我们得到的是
//Array.prototype.push.call(arr , "a");
//即 arr.push("a")
};
};

var arr = new Array();
Array.prototype.push.call(arr, "a"); //arr == ["a"]

var push = Array.prototype.push.uncurrying();
var arr = new Array();
push(arr, "a"); //arr == ["a"]
push(arr, "b"); //arr == ["a","b"]

var toUpperCase = String.prototype.toUpperCase.uncurrying();
var arr1 = arr.map(function(elem) {
return toUpperCase(elem); //map()迭代数组元素 A ,B,并把结果放在一个新数组中返回
})

console.log(arr1); //["A", "B"]

var arr2 = arr.forEach(function(elem, index) {
return toUpperCase(index + "." + elem);//foreach()只迭代数组元素,没有返回值 1.a 2.b
})

console.log(arr2); //undefined

var selfindexof = function() {

var ary = Array.prototype.shift.call(arguments);
return Array.prototype.indexOf.apply(ary, arguments);
//等价于 return Function.prototype.call.apply(Array.prototype.indexOf,arguments);

}

console.log(selfindexof(arr, "b"));// 1

var add_fn = function(obj, fn_keys) {
for (var i = 0, fn; fn = fn_keys[i++];) {~
~function(fn) {
var new_fn = Array.prototype[fn].uncurrying();
obj[fn] = function() {
new_fn.apply(this, [this].concat(Array.prototype.slice.call(arguments)));
//arguments是Object,Array.prototype.slice.call(arguments)将arguments转化成数组
//如果不转化concat之后得到的是[this,Object]
//转化之后concat之后得到的是[this,arguments[0],arguments[1]...]

return this;
};
}(fn)
}
}

var A = function() {

}

add_fn(A.prototype, ['push', 'indexOf', 'shift', 'pop', 'forEach']);

var a = new A;

console.log(a.push)
a.push(4).push(5).push(6).forEach(function(n, i) {
// alert(n);
})

/*科里化*/
Function.prototype.currying = function(){
//形成了闭包,所以_args会常驻内存中,因为闭包依赖于外部函数的变量
var _args = [];
var _this = this;
return function(){
if (arguments.length === 0) {
return _this.apply(this,_args);
}
[].push.apply(_args, arguments);
return arguments.callee;
}
}

//实现惰性计算
var monthly_cost = 0;

var monthly_cost_fn = function() {
for (var i = 0, c; c = arguments[i++];) {
monthly_cost += c;
}
return monthly_cost;
}.currying();

/*此时的monthly_cost_fn = function(){
if (arguments.length === 0) {
return _this.apply(this,_args);
}
[].push.apply(_args, arguments);
return arguments.callee;
}*/

monthly_cost_fn(100);
monthly_cost_fn(200);//有参数不会去计算,而是把参数存贮起来
monthly_cost_fn(300);

console.log(monthly_cost_fn.call());//参数为0,会去执行计算,得出600

Currying and Uncurrying Js的更多相关文章

  1. js高阶函数应用—函数柯里化和反柯里化(二)

    第上一篇文章中我们介绍了函数柯里化,顺带提到了偏函数,接下来我们继续话题,进入今天的主题-函数的反柯里化. 在上一篇文章中柯里化函数你可能需要去敲许多代码,理解很多代码逻辑,不过这一节我们讨论的反科里 ...

  2. JavaScript进阶之路——认识和使用Promise,重构你的Js代码

    一转眼,这2015年上半年就过去了,差不多一个月没有写博客了,"罪过罪过"啊~~.进入了七月份,也就意味着我们上半年苦逼的单身生活结束了,从此刻起,我们要打起十二分的精神,开始下半 ...

  3. (转)Array.prototype.slice.call自解

    很多框架或者库里面都会有这句的使用,最多的还是通过Array.prototype.slice.call(arguments,0)把arguments这个伪数组转换为真正的数组.但为什么可以这么做,却一 ...

  4. 彻底理解Javascript 中的 Promise(-------------------------------***---------------------------------)

    ES6原生提供了 Promise 对象. 到底是何方妖怪呢?打出来看看: 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个 ...

  5. JS中的反柯里化( uncurrying)

    反柯里化 相反,反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用.即把如下给定的函数签名, obj.func(arg1, arg2) 转化成一个函数形式,签名 ...

  6. JS中的柯里化(currying)

    何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参 ...

  7. js 柯里化Currying

    今天读一篇博客的时候,看都有关柯里化的东西,由于好奇,特意查了一下,找到一篇比较好的文章,特意收藏. 引子先来看一道小问题:有人在群里出了到一道题目:var s = sum(1)(2)(3) .... ...

  8. JS中的柯里化(currying) 转载自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]

    JS中的柯里化(currying) by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpr ...

  9. Js中Currying的应用

    Js中Currying的应用 柯里化Currying是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术,是函数式编程应用. 描述 如果说函数式编程中有两 ...

随机推荐

  1. 关于Struts2配置文件名修改的问题

    突发奇想的想知道Struts2的配置文件名是否可以修改,自己最早使用Struts2的时候,只是单纯的将配置文件命名为“struts.xml”,这是Strut2默认的配置文件名,我一直也没有去修改它的命 ...

  2. 多个else if语句

    public class demo { public static void main(String[] args) { boolean examIsDone = true; int score = ...

  3. 深入浅出 Java Concurrency (7): 锁机制 part 2 AQS

      在理解J.U.C原理以及锁机制之前,我们来介绍J.U.C框架最核心也是最复杂的一个基础类:java.util.concurrent.locks.AbstractQueuedSynchronizer ...

  4. Shiro学习之路 -- 架构及其组件

    出自:跟我学shiro 简介 Apache Shiro 是 Java 的一个安全框架.目前,使用 Apache Shiro 的人越来越多,因为它相当简单,对比 Spring Security,可能没有 ...

  5. Django 学习之---缓存系统

    一.浏览器缓存机制 Cache-control策略(重点关注) Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务 ...

  6. js调用activeX插件 报异常:TypeError:对象不支持 属性方法

    部署之后的js网页如果调用没有签名的 ocx/dll 插件的话会报异常:TypeError:对象不支持 “init” 属性方法 (init为插件公开的方法) 但是如果写一个htm本地文件去调用插件,和 ...

  7. Android开发实战之ViewPager实现向导界面

    当我们更新应用,或者第一次进入应用时都会有一个向导界面,介绍这个app的内容和使用方式. 如果你细心你会发现其实这就是个viewpager,本篇博文将介绍应用的向导界面是如何制作的.希 望本篇博文对你 ...

  8. 148. Sort List (List)

    Sort a linked list in O(n log n) time using constant space complexity. 法I:快排.快排的难点在于切分序列.从头扫描,碰到> ...

  9. Struts2分模块开发

    -------------------siwuxie095 Struts2 分模块开发 在实际开发中,如果一个项目是团队开发的,也就是很多人开发的, 每个人都需要去修改 struts.xml,因为 s ...

  10. H5 css学习

    p{text-indent:2em;}段前空两格   段落排版--行间距(行高) p{line-height:1.5em;} 段落排版--中文字间距.字母间距  h1{    letter-spaci ...