//反科里化
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. HDU1257题解

    解题思路:这题的本质就是:求一个给定的数字序列中,非递增(或非递减)子序列的最少的条数. 思维误区:本题很容易被样例坑,以为是直接求跳跃点(i < j && ai < aj ...

  2. 学生党如何拿到阿里技术offer:《阿里面试经历-2014.4.18研发实习生面试经历(失败)》

    我们分享的上一篇文章是一位学长在大三的时候面试阿里实习生成功的经历的分享,其实就像学长在上一篇文章最后说的那样“面试并没有想的那么难,运气也会占一部分.”,其实我个人觉得,对于我们而言,自己越努力就会 ...

  3. sqlldr加载 数据文件的字段超出最大长度

    SQLLOAD数据的时候,建表给的字段给够了,建表已经给到VHARCHAR2(1024)了,实际数据是VHARCHAR2(256).加载报错"数据文件的字段超出最大长度"查了半天, ...

  4. leetcode hashmap

    187. Repeated DNA Sequences 求重复的DNA序列 public List<String> findRepeatedDnaSequences(String s) { ...

  5. data-ajax="false"

    转自:https://yq.aliyun.com/ziliao/265393 最近在做一个项目,由于涉及到跨平台性,所以采用了jquerymobile这个框架,在开发过程中,一开始为了图测试方便,采用 ...

  6. webpy简单使用

    #!/usr/bin/env python import web import pymysql.cursors # Connect to the database connection = pymys ...

  7. 易捷框架之EChart 的使用

    需要用到百度的报表控件 ,总结如下: 1,先引入开发包,以及主题包: <%@ include file="./common/echarts_header.jsp"%> ...

  8. iOS开发基础控件--UIButton

    01 //这里创建一个圆角矩形的按钮 02     UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 03 ...

  9. 关于Excel无法打开,因为文件格式或文件扩展名无效的解决方法

    可能有网友也遇到过跟我一样的情况,新建的excel一打开就弹出 这样的错误. 这是因为excel打开的时候会去指定的文件夹找一个模板,以这个模板的样式打开新建的ecxel.所以如果excel打开的时候 ...

  10. 浅析 python中的 print 和 input 的底层区别!!!

    近期的项目中 涉及到相关知识 就来总结一下 ! 先看源码: def print(self, *args, sep=' ', end='\n', file=None): # known special ...