摘要:函数柯里化是指参数逐渐求值的过程。所以对于有两个变量的函数,如果固定了,则得到有一个变量的函数通用实现先看一个简单的例子显然不是一个柯里化的实现。从一个通用的函数可接受任意,柯里化成专用的函数。
函数柯里化是指参数逐渐求值的过程。
我觉得它是:降低通用性,提高专用性。
通常,柯里化是这样的过程,“如果你固定某些参数,你将得到接受余下参数的一个函数”。所以对于有两个变量的函数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 操作
总结柯里化是以逻辑学家哈斯凯尔·加里命名的,
正如它的命名一样,函数柯里化给我们带来的是:解决问题的一种逻辑思维方式。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85984.html
摘要:函数式编程,一看这个词,简直就是学院派的典范。所以这期周刊,我们就重点引入的函数式编程,浅入浅出,一窥函数式编程的思想,可能让你对编程语言的理解更加融会贯通一些。但从根本上来说,函数式编程就是关于如使用通用的可复用函数进行组合编程。 showImg(https://segmentfault.com/img/bVGQuc); 函数式编程(Functional Programming),一...
摘要:有这样的说法,并非柯里化有什么意义,而是,当函数可以作为函数的参数和返回值,成为函数式编程语言后,就会不可避免地产生函数柯里化。函数柯里化允许和鼓励你分隔复杂功能变成更小更容易分析的部分。那么用函数柯里化就能实现提前返回。 #### 前言 在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,...
摘要:作为函数式编程语言,带来了很多语言上的有趣特性,比如柯里化和反柯里化。而反柯里化,从字面讲,意义和用法跟函数柯里化相比正好相反,扩大适用范围,创建一个应用范围更广的函数。作为函数式编程语言,JS带来了很多语言上的有趣特性,比如柯里化和反柯里化。 可以对照另外一篇介绍 JS 柯里化 的文章一起看~ 1. 简介 柯里化,是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩...
摘要:组合的概念是非常直观的,并不是函数式编程独有的,在我们生活中或者前端开发中处处可见。其实我们函数式编程里面的组合也是类似,函数组合就是一种将已被分解的简单任务组织成复杂的整体过程。在函数式编程的世界中,有这样一种很流行的编程风格。 JavaScript函数式编程,真香之认识函数式编程(一) 该系列文章不是针对前端新手,需要有一定的编程经验,而且了解 JavaScript 里面作用域,闭...
摘要:作为函数式编程语言,带来了很多语言上的有趣特性,比如柯里化和反柯里化。在一些函数式编程语言中,会定义一个特殊的占位变量。个人理解不知道对不对延迟执行柯里化的另一个应用场景是延迟执行。不断的柯里化,累积传入的参数,最后执行。作为函数式编程语言,JS带来了很多语言上的有趣特性,比如柯里化和反柯里化。 这里可以对照另外一篇介绍 JS 反柯里化 的文章一起看~ 1. 简介 柯里化(Currying)...
阅读 4274·2021-09-09 09:33
阅读 2349·2019-08-29 17:15
阅读 2331·2019-08-29 16:21
阅读 939·2019-08-29 15:06
阅读 2580·2019-08-29 13:25
阅读 538·2019-08-29 11:32
阅读 3190·2019-08-26 11:55
阅读 2556·2019-08-23 18:24