//反科里化
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. jdbc调用sparksql on yarn

    spark sql访问hive表 1.将hive-site.xml拷贝到spark目录下conf文件夹 2.(非必需)将mysql的jar包引入到spark的classpath,方式有如下两种: 方式 ...

  2. 为什么多线程读写 shared_ptr 要加锁?

    https://www.cnblogs.com/Solstice/archive/2013/01/28/2879366.html 为什么多线程读写 shared_ptr 要加锁? 陈硕(giantch ...

  3. Oracle段高水位(HWM, high water mark)问题

    Oracle对表做全表扫描的时候 ,会扫描完HWM以下的数据块.如果某个表delete(delete操作不会降低高水位)了大量数据,那么这时对表做全表扫描就会做很多无用功,扫描了一大堆数据块,最后发现 ...

  4. msyqld 的 The user specified as a definer ('root'@'%') does not exist 问题

    msyqld 的 The user specified as a definer ('root'@'%') does not exist 问题 造成问题:搭建网站时显示内容不完整. 跟踪tomcat日 ...

  5. 记-cloudstack 更改二级存储

    一.问题是由于当初把二级存储挂载到了根分区的文件系统内,并随着慢慢的模板的增加,容量越来越小. 1.先在cloud 网页界面禁用cloudstack区域 2.然后停止cloudstack-manage ...

  6. 巧用setTimeout函数设置程序后门

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 来谈谈 WebAssembly 是个啥?为何说它会影响每一个 Web 开发者?

    作者:link 原文:What is WebAssembly and why it affects web developers! 你听说过WebAssembly吗?这是由Google, Micros ...

  8. 了解zookeeper

    ZooKeeper操作和维护多个小型的数据节点,这些节点被称为znode,采用类似于文件系统的层级树状结构进行管理.图2-1描述了一个znode树的结构,根节点包含4个个节点,其中三个子节点拥有下一级 ...

  9. C#中的数据格式转换 (未完待更新)

    一.string to int int intA = 0;1.intA =int.Parse(str);2.int.TryParse(str, out intA);3.intA = Convert.T ...

  10. 使用PowerMap生成地图图文

    地区    GDP(亿)广东省    80854江苏省    77388山东省    68024浙江省    47251河南省    40471四川省    32934湖北省    32665河北省  ...