前端开发者进阶之函数反柯里化unCurrying
函数柯里化,是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数。
那么反柯里化函数,从字面讲,意义和用法跟函数柯里化相比正好相反,扩大适用范围,创建一个应用范围更广的函数。使本来只有特定对象才适用的方法,扩展到更多的对象。
看一下通用函数:
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里面,很多函数都不做对象的类型检测,而是只关心这些对象能做什么。
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的更多相关文章
- javascript之反柯里化(uncurrying)
在JavaScript中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型语言的特点.可以通过反柯里化(uncurrying)函数实现,让一个对象去借用一个原 ...
- JS中的反柯里化( uncurrying)
反柯里化 相反,反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用.即把如下给定的函数签名, obj.func(arg1, arg2) 转化成一个函数形式,签名 ...
- javascript之反柯里化uncurrying
使用方法: // 使用 var push=Array.prototype.push.uncurrying(); var obj={ "length": 1, "0&quo ...
- JS 函数的柯里化与反柯里化
===================================== 函数的柯里化与反柯里化 ===================================== [这是一篇比较久之前的总 ...
- 浅析 JavaScript 中的 函数 currying 柯里化
原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...
- 前端开发者进阶之函数柯里化Currying
穆乙:http://www.cnblogs.com/pigtail/p/3447660.html 在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接 ...
- js高阶函数应用—函数柯里化和反柯里化
在Lambda演算(一套数理逻辑的形式系统,具体我也没深入研究过)中有个小技巧:假如一个函数只能收一个参数,那么这个函数怎么实现加法呢,因为高阶函数是可以当参数传递和返回值的,所以问题就简化为:写一个 ...
- js高阶函数应用—函数柯里化和反柯里化(二)
第上一篇文章中我们介绍了函数柯里化,顺带提到了偏函数,接下来我们继续话题,进入今天的主题-函数的反柯里化. 在上一篇文章中柯里化函数你可能需要去敲许多代码,理解很多代码逻辑,不过这一节我们讨论的反科里 ...
- 浅析 JavaScript 中的 函数 uncurrying 反柯里化
柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...
随机推荐
- Java里的if else语句例子
import java.util.Scanner;public class if_else2{ public static void main(String[] args) { Scanner s=n ...
- 【转】移动端viewport的使用
web端网站转移至移动端页面,注意点如下: 1.首先引入viewport调整页面宽度 <meta name="viewport" content="width=de ...
- BZOJ3173 TJOI2013最长上升子序列(Treap+ZKW线段树)
传送门 Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input ...
- 安装了linux系统的设备上不了网怎么办
玩了一阵子的树莓派,曾经计划将其作成一台小小无线路由,但是时间和精力关系始终未成功做成. 同时也有在进行一些arm开发板的学习,突然一天发现arm板直接插上网线不能是不能上网的,又想起之前玩树莓派的时 ...
- Mandelbrot和Julia
概述 mandelbrot julia Mandelbrot 对全体复数z,满足xn+1 = xn2 + z从x0 = 0起,|x|随n值增加不趋于无穷大,则z属于Mandelbrot集 代码 #i ...
- Webpack使用教程二
Webpack提供了很多的命令选项来帮助用户构建应用,如果只是通过命令行来使用这些选项,会显得不方便.为了更好的使用Webpack提供的各种命令选项,我们可以创建一个webpack.config.js ...
- 总结一下一般游戏中3D模型各种勾边方法遇到的工程性问题
以前做过简单的rim light勾边,几何勾边,这次又做了后处理的勾边,工程化的时候,都遇到很多问题,简单总结一下. 首先是火炬之光勾边效果,类似轮廓光的实现,简单的卡通渲染也是通过类似的算法加采样色 ...
- [转]编译VC++程序warning C4819快速解决
文章来自:http://www.cppblog.com/API/archive/2012/11/12/195056.aspx 编译VC++程序的时候出现如下提示警告: warning C4819: T ...
- 统计《ASP.Net特供视频教程》总长度
忽然想统计一下我录制过的视频一共多长时间,由于视频文件很多,一共72个,挨个打开进行累加不是程序员应该想起的办法.所以就打算写一个程序来完成这件事,最核心的问题就是“获得一个视频文件的时长”. ffm ...
- Gedit中文乱码
缺省配置下,用 Ubuntu 的文本编辑器(Gedit)打开GB18030(繁体中文用户请将这里的出现的GB18030替换成BIG5或BIG5-HKSCS)类型的中文编码文本文件时,将会出现乱码. 出 ...