函数柯里化,是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数。

那么反柯里化函数,从字面讲,意义和用法跟函数柯里化相比正好相反,扩大适用范围,创建一个应用范围更广的函数。使本来只有特定对象才适用的方法,扩展到更多的对象。

看一下通用函数:

Function.prototype.currying = function() {
var that = this;
return function() {
return Function.prototype.call.apply(that, arguments);
}
}

短小精悍,科学上讲,浓缩的都是精品,但越精品的往往越难以理解。分解一下:

1 为Function原型添加unCurrying方法,这样所有的function都可以被借用;

2 返回一个借用其它方法的函数,这是目的;

3 借用call方法实现,但call方法参数传入呢?借用apply,至此完毕。

回头看看,好像也不难!

还有其它的实现方式:

Function.prototype.unCurrying = function () {
var f = this;
return function () {
var a = arguments;
return f.apply(a[0], [].slice.call(a, 1));
};
};
Function.prototype.unCurrying = function () {
return this.call.bind(this);
};

原理都相同,最终是把this.method转化成 method(this,arg1,arg2....)以实现方法借用和this的泛化。

鸭式辩型:如果一个对象可以像鸭子一样走路,游泳,并且嘎嘎叫,就认为这个对象是鸭子,哪怕它并不是从鸭子对象继承过来的。

在javascript里面,很多函数都不做对象的类型检测,而是只关心这些对象能做什么。

Array构造器和String构造器的prototype上的方法就被特意设计成了鸭子类型。这些方法不对this的数据类型做任何校验。这也就是为什么arguments能冒充array调用push方法.
看下v8引擎里面Array.prototype.push的代码:
function ArrayPush() {
var n = TO_UINT32(this.length);
var m = %_ArgumentsLength();
for (var i = 0; i < m; i++) {
this[i + n] = %_Arguments(i); //属性拷贝
this.length = n + m; //修正length
return this.length;
}
}

这就给对象冒充创造了条件,也就我们讨论的函数柯反里化unCurrying。反柯里化其实反映的是一种思想,扩大方法的适用范围!

看下面例了,让一个普通对象具备push方法:

var push = Array.prototype.push.unCurrying(),
obj = {};
push(obj, 'first', 'two');
console.log(obj);
/*obj {
0 : "first",
1 : "two"
}*/

obj被push了两个元素:first 和two,同时还具备了一个length属性,其实我们创建了一类数组对象。

再看一个例子:

var toUpperCase = String.prototype.toUpperCase.unCurrying();
console.log(toUpperCase('avd')); // AVD function AryUpper(ary) {
return ary.map(toUpperCase);
} console.log(AryUpper(['a', 'b', 'c'])); // ["A", "B", "C"]

只是方法都可以借用。包括call方法。

var call = Function.prototype.call.unCurrying();
function $(id) {
return this.getElementById(id);
}
var demo = call($, document, 'demo');
console.log(demo);

这似乎看起来相对于前两个例子,比较难理解,其实一句话就可以解释:document借用了$方法,并替换了其中的this。

在函数柯里化例子中bind的例子中,柯里化的目的是为了固定可变参数this。而反柯里化,把原来拥有方法的this泛化了,泛化到所有对象都可以借用,也就是替代当前拥有方法的this。

这里,希望不要混淆,这里的this并不是指上例中的this,上例中的this只是因为借用的方法是call。

更有趣的是,unCurrying本身也是方法,它是否可以被借用呢?答案是肯定的。这就是js的奇妙之处,反柯里化的奇妙之处。

看下面:

var unCurrying = Function.prototype.unCurrying.unCurrying();
var map = unCurrying(Array.prototype.map);
var sq = map([1, 2, 3],
function(n) {
return n * n;
});
console.log(sq); // [1,4,9]

无论是柯里化还是反柯里化,其实反应的都是一种设计思想。这一节先到这里。

 

前端开发者进阶之函数反柯里化unCurrying的更多相关文章

  1. javascript之反柯里化(uncurrying)

    在JavaScript中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型语言的特点.可以通过反柯里化(uncurrying)函数实现,让一个对象去借用一个原 ...

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

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

  3. javascript之反柯里化uncurrying

    使用方法: // 使用 var push=Array.prototype.push.uncurrying(); var obj={ "length": 1, "0&quo ...

  4. JS 函数的柯里化与反柯里化

    ===================================== 函数的柯里化与反柯里化 ===================================== [这是一篇比较久之前的总 ...

  5. 浅析 JavaScript 中的 函数 currying 柯里化

    原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...

  6. 前端开发者进阶之函数柯里化Currying

    穆乙:http://www.cnblogs.com/pigtail/p/3447660.html 在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接 ...

  7. js高阶函数应用—函数柯里化和反柯里化

    在Lambda演算(一套数理逻辑的形式系统,具体我也没深入研究过)中有个小技巧:假如一个函数只能收一个参数,那么这个函数怎么实现加法呢,因为高阶函数是可以当参数传递和返回值的,所以问题就简化为:写一个 ...

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

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

  9. 浅析 JavaScript 中的 函数 uncurrying 反柯里化

    柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...

随机推荐

  1. (转)MVC中的Repository模式

    1.首先创建一个空的MVC3应用程序,命名为MyRepository.Web,解决方案命名为MyRepository. 2.添加一个类库项目,命名为MyRepository.DAL,添加一个文件夹命名 ...

  2. ElasticSearch学习笔记-01 简介、安装、配置与核心概念

    一.简介 ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进 ...

  3. Asp.Net Web API 2第十八课——Working with Entity Relations in OData

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html. 本文的示例代码的下载地址 ...

  4. Salesforce 生成测试可用 Id

    在写 Test Class 的时候,有时候需要一批有 Id 的数据或者把 Id 作为参数等情况,在数据关系比较复杂的情况下去造真实数据有些麻烦,于是找到这样一个可以生成 Id 的方法可以用来辅助测试! ...

  5. 团队项目--站立会议 DAY3

    小组名称:D&M 参会人员:张靖颜,钟灵毓秀,何玥,赵莹,王梓萱 今天是站立会议的第三天 在前两次会议的基础上 组员们总结了自己在任务中的经验 个抒己论在会议中进行了一些讨论 并且对接下来的工 ...

  6. Windows 8.1 开发过程中遇到的小问题

    最近在开发Windows 8 应用的时候碰到了一个莫名的问题,错误内容如下:(其中 **.DLL是本地创建的项目,在主项目中添加了引用,其中大部分代码是MVVM light 框架库的代码) Syste ...

  7. tomcat通过conf-Catalina-localhost目录发布项目详解

    Tomcat发布项目的方式大致有三种,但小菜认为通过在tomcat的conf/Catalina/localhost目录下添加配置文件,来发布项目,是最佳选择. 因为这样对tomcat的入侵性最小,只需 ...

  8. js围绕屏幕转圈的方块

    点击运动按钮后,方块会挨着浏览器的边,从左到右,从上到下转一圈. 这个我居然写了几天,我也是不想说什么咯. 完成代码一: <!-- Author: XiaoWen Create a file: ...

  9. paip.环境配置整合 ibatis mybatis proxool

    paip.环境配置整合 ibatis mybatis proxool  索引: ///////////1.调用 ///////////////2. ibatis 主设置文件  com/mijie/ho ...

  10. RAR和ZIP:压缩大战真相

    转:http://fqd2eh4y.blog.163.com/blog/static/69195855200801035015857 前言--王者归来? 等待足足两年之久,压缩霸主WinZip终于在万 ...