本文转自: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. 选中没有选中的复选框,匹配含有某个字符串的正则,json取值的两种方法,把变量定义在外面跟里面的区别

    一.筛选没有选中的复选框:not("input:checked") 二.匹配有VARCHAR的字符串:".*VARCHAR.*?" 三.json取值的两种方法 ...

  2. 如何实现桌面App图标可以动态显示消息数(类似手机上的QQ图标)?

    手机上的APP , 像QQ和微信等都可以在图标上动态显示消息数(最大99) , 那么你有没有想过这些效果是如何实现的?桌面上开发的传统应用程序能否也实现类似的功能? 1 思路 桌面快捷方式的图标本质上 ...

  3. Dom Animator – 提供 Dom 注释动画的 JS 库

    DOM 动画是一个极好的 JavaScript 库,用来在页面的 DOM 注释中显示小的 ASCII 动画.这对于那些检查你的代码的人是一个小彩蛋,仅此而已.它是一个独立的库,不依赖 jQuery 或 ...

  4. JavaScript 事件绑定及深入

    一.传统事件绑定的问题 解决覆盖问题,我们可以这样去解决:window.onload = function () { //第一个要执行的事件,会被覆盖 alert(1);};if (typeof wi ...

  5. [deviceone开发]-纳豆项目源码开源

    一.简介 已上线的纳豆项目开源.这个App做的非常好,细节处理的很流畅,使用了很多小的动画效果,极力推荐,很多功能可以从这个应用中获取代码和灵感. 二.效果图        三.相关下载 androi ...

  6. 微信 小程序 canvas

    测试手机为IPHONE6,开发者工具版本0.10.102800.开发者工具0.11.112301版本也一样 微信小程序里的canvas 非 h5 canvas有很多不一样的地方,以下把微信小程序的ca ...

  7. 深入源码分析使用jQuery连续发起jsonp请求失败的原因

    jQuery的 jsonp 大家应该是十分熟悉了.曾遇到过这样的需求1.希望请求几个相似的内容添加到页面2.请求的内容一定时间内是固定不变的,希望做个缓存. 于是脑子一拍写下了类似这样的代码 for( ...

  8. 刀锋上前行!绕过Ramint蠕虫病毒直接脱壳

    系统 : Windows xp 程序 : 某游戏客户端 程序下载地址 :不提供 要求 : 脱去压缩壳 使用工具 : OD & PEID & LordPE & Import RE ...

  9. MAPINFO中利用GridMaker工具创建栅格图层

    在工作中需要使用栅格地图,以往都是由研发人员来创建,今天偶然发现Mapinfo中有GridMaker这样一个工具,结合网络搜索自己试了一下,居然做成功了,这里把步骤记录下来,方便以后查看. 1.首先在 ...

  10. 关于SharePoint 2013 UserProfile跨场的几点注意

    1.跨场中需要以下几个Service实例,没有这几个会遇到各种问题 2.发布场和消费场同时需要创建Host站点,否则消费场的SiteFeed无法使用. 3.跨场关注的问题请参考:http://www. ...