本文转自:https://segmentfault.com/a/1190000003733107

函数柯里化是指参数逐渐求值的过程。

我觉得它是:降低通用性,提高专用性。

通常,柯里化是这样的过程,“如果你固定某些参数,你将得到接受余下参数的一个函数”。所以对于有两个变量的函数y^x,如果固定了 y=2,则得到有一个变量的函数 2^x

通用实现

全选复制放进笔记
function currying(fn) {
var slice = Array.prototype.slice;
var args = alice.call(arguments, 1);
return function() {
var innerArgs = slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
}
}

先看一个简单的例子

全选复制放进笔记
function add(num1, num2) {
return num1 + num2;
} function curryAdd(num) {
return num + 5;
} add(2, 4); // 6
curryAdd(1); // 6

curryAdd 显然不是一个柯里化的实现。但是它很好的诠释了柯里化的思想。add 函数有两个参数,curryAdd 固定了其中一个参数


用上面 currying 函数构造 curryAdd 函数。

全选复制放进笔记
var curryAdd5 = currying(add, 5);

var curryAdd4 = currying(add, 4);

curryAdd5(1); // 6

curryAdd4(1); // 5

再看一个经典的 ajax 例子。

全选复制放进笔记
function Ajax() {
this.xhr = new XMLHttpRequest();
} Ajax.prototype.open = function(type, url, data, callback) {
this.onload = function() {
callback(this.xhr.responseText, this.xhr.status, thix.xhr);
} this.xhr.open(type, url, data.async);
this.xhr.send(data.paras);
} ['get', 'post'].forEach(function(type) {
Ajax.prototype[type] = currying(Ajax.prototype.open, type);
}) var xhr = new Ajax(); xhr.get('/articles/list', {}, function(datas) {}); xhr.post('/articles/add', {}, function(datas) {});

get post 两个方法是通过 'open' 方法衍生出来的。

从一个通用的 open 函数(可接受任意type),柯里化成专用的函数 get、post。


固定易变因数

提前把易变因数固定下来,生成一个更明确的应用函数,最典型的代码就是 ES5 定义的 Function.prototype.bing 函数

全选复制放进笔记
Function.prototype.bing = function(context) {
var _this = this,
slice = Array.prototype.slice,
_args = slice.call(arguments, 1); return function() {
return _this.apply(context, _args.concat(slice.call(arguments)))
}
}

延迟执行

不断的柯里化,累积传入的参数,最后执行。

全选复制放进笔记
function add() {
var sum = 0, i, len;
for (i = 0, len = arguments.length; i < len; i++) {
sum += arguments[i];
}
return sum;
} var currying = function(fn) {
var _args = []; return function cb() {
if (arguments.length === 0) {
return fn.apply(this, _args);
} Array.prototype.push.apply(_args, arguments); return cb;
}
} var curryingAdd = currying(add); curryingAdd(1)(2)(3)(4)(); // 10 var add321 = curryingAdd(3)(2, 1); add321(4)(); // 10

性能

柯里化肯定会有一些开销(函数嵌套,比普通函数占更多内存),但性能瓶颈首先来自其它原因(DOM 操作等)。

从另外一个角度分析,不管你用不用柯里化这个思维,你的代码很可能已经步入了更复杂的模式,会有更大的开销。

有关性能的一些事:

  • 存取 arguments 对象通常要比存取命名参数要慢一些。

  • 一些老版本的浏览器在 arguments.length 的实现上相当慢。

  • 使用 fn.apply() 和 fn.call() 要比直接调用 fn() 要慢点。

  • 创建大量嵌套作用域和闭包会带来开销,无论是内容还是速度上。

  • 大多数瓶颈来自 DOM 操作


总结

柯里化是以逻辑学家哈斯凯尔·加里命名的,

正如它的命名一样,函数柯里化给我们带来的是:解决问题的一种逻辑思维方式。

[转]js函数式变成之函数柯里化的更多相关文章

  1. 【转载】JS中bind方法与函数柯里化

    原生bind方法 不同于jQuery中的bind方法只是简单的绑定事件函数,原生js中bind()方法略复杂,该方法上在ES5中被引入,大概就是IE9+等现代浏览器都支持了(有关ES5各项特性的支持情 ...

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

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

  3. 前端面试手写代码——JS函数柯里化

    目录 1 什么是函数柯里化 2 柯里化的作用和特点 2.1 参数复用 2.2 提前返回 2.3 延迟执行 3 封装通用柯里化工具函数 4 总结和补充 1 什么是函数柯里化 在计算机科学中,柯里化(Cu ...

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

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

  5. JS 浅谈函数柯里化,不明觉厉

    在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 Christopher ...

  6. JS:函数柯里化

    函数柯里化 柯里化 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术. 简单来说,就 ...

  7. js bind es5函数柯里化

    绑定函数 bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值.常见的错误就像上面的例子一样,将方法从对象中拿出来,然后调用,并且希望this指向原来的对象. 如果不做特 ...

  8. Scala 基础(十二):Scala 函数式编程(四)高级(二)参数(类型)推断、闭包(closure)、函数柯里化(curry)、控制抽象

    1  参数(类型)推断 参数推断省去类型信息(在某些情况下[需要有应用场景],参数类型是可以推断出来的,如list=(1,2,3) list.map() map中函数参数类型是可以推断的),同时也可以 ...

  9. JavaScript函数柯里化的一些思考

    1. 高阶函数的坑 在学习柯里化之前,我们首先来看下面一段代码: var f1 = function(x){ return f(x); }; f1(x); 很多同学都能看出来,这些写是非常傻的,因为函 ...

随机推荐

  1. 学习HTML5之表单

    HTML5 的标准已经定了,应该火了,或者已经火了.那么是不是可以学习一下呢? 目前h5的主场还是在手机端,pc还是受困于浏览器的兼容,主要是IE在拖后腿.所以这里侧重的是手机里面的表现. 先来看看表 ...

  2. svn服务端和eclipse配合使用

    今天弄了个svn服务器来做项目的版本控制,讲讲我做的步骤吧 1.安装svn服务端 2.下载subclipse插件 3.将subclipse插件安装到eclipse上,点击Install New Sof ...

  3. Eclipse开发STM32出现找不到函数的情况的解决方法

    问题表现: 在明明引用了头文件的情况下,出现“undefined reference to  `…'”的情况,例如下图: 解决方法: 在左边的数据目录定位到“system\src\stm32f0-st ...

  4. JEPF 3.1.2 发布,我们的软件机床(软件快速开发平台)

    JEPF新一代软件快速开发平台(Java Elephant Platform)是一款优秀的平台产品,它本着灵活.快捷开发.高性能.高协作性.高稳定性.高可用性.人性化的操作体验为设计宗旨历经2年研发成 ...

  5. OPENGLES 基础(一些链接和随笔)

    http://imgtec.eetrend.com/blog/3912 http://blog.csdn.net/zj8792612/article/details/16116145   在线着色器编 ...

  6. JavaScript学习07 内置对象

    JavaScript内置对象 图像对象 导航对象 窗口对象 屏幕对象 事件对象 历史对象 文件对象(重要) 锚点对象 链接对象 框架对象 表单对象(重要) 位置对象 JS Window 窗口对象:ht ...

  7. 腾讯bugly团队提供的android国内镜像

    腾讯bugly团队提供的国内镜像   如果使用Android SDK Manager下载比较慢或者打不开,可以使用国内镜像 使用说明 http://android-mirror.bugly.qq.co ...

  8. 阿帕奇apache服务器和webDav服务器快速配置。

    当自己在家敲代码需要发请求时,就可以配置本地apache,Mac电脑自带的服务器.这个比windows上的本地服务器还要好用,下面写下最快速配置方案. 0.在开始之前需要给自己的电脑设置下开机密码,想 ...

  9. mac os intellij如何快路查看一个java类的所有方法,结构

    如果是自己写的java类,点击点击导航的project-setting-show members 如果是系统库的,点击structure 再点一下lib中的类,或者快捷键 command+F12

  10. iOS远程推送原理及实现过程

    ➠更多技术干货请戳:听云博客 推送通知,是现在的应用必不可少的功能.那么在 iOS 中,我们是如何实现远程推送的呢?iOS 的远程推送原理又是什么呢?在做 iOS 远程推送时,我们会遇到各种各样的问题 ...