[转]js函数式变成之函数柯里化
本文转自: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函数式变成之函数柯里化的更多相关文章
- 【转载】JS中bind方法与函数柯里化
原生bind方法 不同于jQuery中的bind方法只是简单的绑定事件函数,原生js中bind()方法略复杂,该方法上在ES5中被引入,大概就是IE9+等现代浏览器都支持了(有关ES5各项特性的支持情 ...
- js高阶函数应用—函数柯里化和反柯里化(二)
第上一篇文章中我们介绍了函数柯里化,顺带提到了偏函数,接下来我们继续话题,进入今天的主题-函数的反柯里化. 在上一篇文章中柯里化函数你可能需要去敲许多代码,理解很多代码逻辑,不过这一节我们讨论的反科里 ...
- 前端面试手写代码——JS函数柯里化
目录 1 什么是函数柯里化 2 柯里化的作用和特点 2.1 参数复用 2.2 提前返回 2.3 延迟执行 3 封装通用柯里化工具函数 4 总结和补充 1 什么是函数柯里化 在计算机科学中,柯里化(Cu ...
- js高阶函数应用—函数柯里化和反柯里化
在Lambda演算(一套数理逻辑的形式系统,具体我也没深入研究过)中有个小技巧:假如一个函数只能收一个参数,那么这个函数怎么实现加法呢,因为高阶函数是可以当参数传递和返回值的,所以问题就简化为:写一个 ...
- JS 浅谈函数柯里化,不明觉厉
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 Christopher ...
- JS:函数柯里化
函数柯里化 柯里化 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术. 简单来说,就 ...
- js bind es5函数柯里化
绑定函数 bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值.常见的错误就像上面的例子一样,将方法从对象中拿出来,然后调用,并且希望this指向原来的对象. 如果不做特 ...
- Scala 基础(十二):Scala 函数式编程(四)高级(二)参数(类型)推断、闭包(closure)、函数柯里化(curry)、控制抽象
1 参数(类型)推断 参数推断省去类型信息(在某些情况下[需要有应用场景],参数类型是可以推断出来的,如list=(1,2,3) list.map() map中函数参数类型是可以推断的),同时也可以 ...
- JavaScript函数柯里化的一些思考
1. 高阶函数的坑 在学习柯里化之前,我们首先来看下面一段代码: var f1 = function(x){ return f(x); }; f1(x); 很多同学都能看出来,这些写是非常傻的,因为函 ...
随机推荐
- [Cordova] 无法显示Alert视窗
[Cordova] 无法显示Alert视窗 问题情景 今天开了一个Cordova专案做范例,将预设的index.html页面修改为下列内容.按下执行却发现,这样一个简单的范例无法正常执行.点击页面上的 ...
- TwentyTwenty – 使用 jQuery 实现图片对比功能
这是一款非常棒的图片对比工具,能够方便的应用到你的网站中.其基本思路是把两张图片层叠在一起,当你拖动滑竿的时候,利用 CSS clip 裁剪图片,进行形成视觉对比效果. 您可能感兴趣的相关文章 Met ...
- Droidicon – 1600+ 漂亮的 Android 图标
Droidicon 提供超过1600款定制图标,让你可以超级容易的把图标和徽章添加到您的应用程序中.你可以自定义你想要的各种形式的图标,给图标添加描边,透明度和颜色过滤器.包括这些 Google Ma ...
- Web Uploader - 功能齐全,完美兼容 IE 的上传组件
文件上传是网站和 Web 应用程序的常用功能,一直没有一款完美的文件上传组件,因此让很多开发人员碰到头疼的浏览器兼容问题. WebUploader 是由 Baidu FEX 团队开发的一款以 HTML ...
- Kotlin:Android世界的Swift
转自:http://www.infoq.com/cn/news/2015/06/Android-JVM-JetBrains-Kotlin Kotlin是一门与Swift类似的静态类型JVM语言,由Je ...
- Android不同屏幕适配
1.尽量使用线性布局(LinearLayout)和相对布局(RelativeLayout),不要使用绝对布局. 2.尽量使用dip和sp,不要使用px. 3.为不同的分辨率提供不同的布局文件和图片. ...
- objective-c系列-NSMutableString
********************************************** NSMutableString为NSString的子类,除了父类的方法,NSMutableStirng还有 ...
- python 判断学期与学年
9,10,11,12,1 第一学期 2,3,4,5,6,7 第二学期 其中8月份放假,暂且放入第一学期.因为大部分学校都选在8月底开学 import datetime def getXNandXQ() ...
- raw_input() 与 input() __ Python
这两个均是 python 的内建函数,通过读取控制台的输入与用户实现交互.但他们的功能不尽相同.举两个小例子. 1 >>> raw_input_A = raw_input(" ...
- js去掉字符串前后空格的五种方法
转载 :http://www.2cto.com/kf/201204/125943.html 第一种:循环检查替换[javascript]//供使用者调用 function trim(s){ ret ...