函数柯里化
来源:互联网 发布:php网教视频网站源码 编辑:程序博客网 时间:2024/05/16 10:15
含义:柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程。
柯里化一个求和函数
var add = function (a, b, c) { return a+b+c;};var addCurrying= function(a) { return function (b) { return function (c) { return a+b+c; }; };};console.log(add(1,2,3)); //6console.log(addCurrying(1));//functionconsole.log(addCurrying(1)(2));//functionconsole.log(addCurrying(1)(2)(3)); //6
可以看到, addCurrying(1) 是一个 Function,每次调用都返回一个新的函数,该函数接受另一个调用,然后又返回一个新的函数,直至最后返回结果,分布求解,层层递进。(PS:这里利用了闭包的特点)
那么现在我们更进一步,如果要求可传递的参数不止3个,可以传任意多个参数,当不传参数时输出结果?
首先来个普通的实现:
//归并var add = function(items){ return items.reduce(function(a,b){ return a+b });};console.log(add([1,2,3,4])); //10
但如果要求把每个数乘以10之后再相加,那么:
var add = function (items,multi) { return items.map(function (item) { return item*multi; }).reduce(function (a, b) { return a + b });};console.log(add([1, 2, 3, 4],10)); //100
好在有 map 和 reduce 函数,假如按照这个模式,现在要把每项加1,再汇总,那么我们需要更换map中的函数。
下面看一下柯里化实现:
var add = function () { var _args = []; return function () { if (arguments.length === 0) { return _args.reduce(function (a, b) { return a + b; }); } [].push.apply(_args, [].slice.call(arguments)); return arguments.callee; }}; var sum = add();console.log(sum); // Functionsum(100,200)(300); // 调用形式灵活,一次调用可输入一个或者多个参数,并且支持链式调用sum(400);console.log(sum()); // 1000 (加总计算)
上面 add是柯里化了的函数,它返回一个新的函数,新的函数接收可分批次接受新的参数,延迟到最后一次计算。
通用的柯里化函数
var curry = function(fn) { var _args = [] return function cb() { if (arguments.length == 0) { return fn.apply(this, _args) } Array.prototype.push.apply(_args, arguments); return cb; }}
柯里化的基础
上面的代码其实是一个高阶函数(high-order function), 高阶函数是指操作函数的函数,它接收一个或者多个函数作为参数,并返回一个新函数。此外,还依赖与闭包的特性,来保存中间过程中输入的参数。即:
1.函数可以作为参数传递
2.函数能够作为函数的返回值
3.闭包
柯里化的作用
1.延迟计算。上面的例子已经比较好低说明了。
2.参数复用。当在多次调用同一个函数,并且传递的参数绝大多数是相同的,那么该函数可能是一个很好的柯里化候选。
3.动态创建函数。这可以是在部分计算出结果后,在此基础上动态生成新的函数处理后面的业务,这样省略了重复计算。或者可以通过将要传入调用函数的参数子集,部分应用到函数中,从而动态创造出一个新函数,这个新函数保存了重复传入的参数(以后不必每次都传)。例如,事件浏览器添加事件的辅助方法:
var addEvent = function(el, type, fn, capture) { if (window.addEventListener) { el.addEventListener(type, function(e) { fn.call(el, e); }, capture); } else if (window.attachEvent) { el.attachEvent("on" + type, function(e) { fn.call(el, e); }); } };
每次添加事件处理都要执行一遍 if…else…,其实在一个浏览器中只要一次判定就可以了,把根据一次判定之后的结果动态生成新的函数,以后就不必重新计算。
var addEvent = (function(){ if (window.addEventListener) { return function(el, sType, fn, capture) { el.addEventListener(sType, function(e) { fn.call(el, e); }, (capture)); }; } else if (window.attachEvent) { return function(el, sType, fn, capture) { el.attachEvent("on" + sType, function(e) { fn.call(el, e); }); }; }})();
这个例子,第一次 if…else… 判断之后,完成了部分计算,动态创建新的函数来处理后面传入的参数,这是一个典型的柯里化。
- 函数柯里化
- 函数柯里化
- 函数柯里化
- 函数柯里化
- 函数柯里化
- 函数柯里化
- 函数柯里化
- 函数柯里化
- 惰性函数与柯里化函数
- 函数柯里化与函数绑定
- 【scala 函数定义和调用】Scala的函数调用:普通函数、匿名函数、柯里化函数
- JavaScript之函数绑定与函数柯里化(高级函数)
- 函数-JavaScript 中的 函数 currying 柯里化
- 函数式编程之柯里化函数
- Python中的函数柯里化
- JavaScript 函数的柯里化
- 柯里化函数之Javascript
- 函数柯里化(Currying)
- 剪邮票
- 关于Flask mega-tutorial遇到的一些问题(外网访问+OpenId)
- Git提交代码简单指令
- POJ 1157 dp
- JAVA OOP第八章JDBC 上机+课后
- 函数柯里化
- HM学习二
- JSP注释
- Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property 'xxx'
- Trace32 加载MTK平台 SYS_MINI_RDUMP
- 文件流读取之EOF与Peek
- nginx学习8——nginx服务器信息隐藏,服务器名称修改
- 线性回归与逻辑斯提回归的区别
- 104 微服务基础概念