函数Curry化
之前写过一个函数Curry化的小文章
那会儿对Curry化的理解不够深,平时遇到的需要Curry化的例子也比较少,今天,重新整理这个问题
函数Curry化,其实就是将一个参数非常多的函数,在大多数参数都相同的情况下,生成一个新的参数比较少的函数的过程
但是,有一个无法解决的问题,至少我不知道该怎么办,就是只能按顺序去省略参数
上代码,先从简单的例子说起
function add( a , b , c){
return a + b + c;
}
该方法可以计算三个数的合.
add(1,2,3);
add(1,2,4);
add(1,2,5);
....
遇到这种情况,总是写重复的参数,会不会觉得烦?不会?那看看下面的代码
function getPosition( iWidth , iHeight , iMarginBottom , iMarginRight , /* 一共有几列 */iColNum , iIndex ){
return {
left : iIndex % iColNum * ( iMarginRight + iWidth ),
top : Math.floor( iIndex / iColNum ) * ( iMarginBottom + iHeight )
}
}
假如现在需要实现一个发牌的效果,需要将每个元素都用绝对定位放到指定的位置上.

像这样.通过这个方法,只要将每个方块的各个属性和方块的索引index传递到getPosition方法里,就可以获取它应在的位置的坐标
假如现在有了一个新功能,通过点击某个按钮,可以让他们按照倒序排列
假如现在又有了一个新功能,通过点击某个按钮,可以增加新的方块
假如...
好吧,看来,getPosition()方法里的前五个参数,恐怕要多填几次了.
这时候,如果使用函数Curry化,就可以让代码看起来更清楚了,
继续使用add方法做说明,并且,将三个数相加减少到两个,
然后演示下函数Curry化的过程
代码如下:
function add( a , b ){
if( typeof b == "undefined" ){
return function (b){
return a + b;
}
}
}
使用方法:
var add3 = add(3) alert( add3(4) )
上面的add方法中,返回了一个闭包,将第一参数a保存在了这个闭包中,同时接收一个新的参数b
这样,当我们需要大量使用add(3,??)的时候,就可以使用新的函数add3()来进行计算了.
但是,每次都这样去写,是得不偿失的,尤其是到了参数真的多起来的时候,更是愚蠢,因此,需要封装一个方法,实现Curry化
首先,需要补充点小知识点
1.function里的argumens,并不是一个真正的数组
2.arrObject.slice(start,/*optional*/end) 方法, 可以返回一个数组里[start,end)部分的元素,当只填写了start参数时,会获取从start开始一直到结尾的元素,这个方法不会改变原来的数组
3.Array.prototype.slice 可以将arguments转化为一个真正的数组.
知识点3的测试代码如下
var mySlice = Array.prototype.slice;function test(a,b,c,d){
//通过mySlice可以将arguments转换为一个真正的数组
console.dir(mySlice.call(arguments))
}
test(1,2,3,4)
控制台显示Array[4];
最终函数Curry化代码如下
function curry(fn/*,arg1,arg2,arg3,......*/){
var mySlice = Array.prototype.slice;
var save_args = mySlice.call(arguments,1)
return function (){
var newArgs = mySlice.call(arguments);
var args = save_args.concat(newArgs);
return fn.apply(null,args)
}
}
从原理到中间利用的知识点,已经说的比较清楚了,不再赘述.
附加测试代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<style>
*{ margin:0; padding:0;}
ul{ list-style:none;}
li{ position:absolute; width:100px; height:100px; background-color:#000;}
</style>
<script>
function getPosition( iWidth , iHeight , iMarginBottom , iMarginRight , /* 一共有几列 */iColNum , iIndex ){
return {
left : iIndex % iColNum * ( iMarginRight + iWidth ),
top : Math.floor( iIndex / iColNum ) * ( iMarginBottom + iHeight )
}
}
function curry(fn/*,arg1,arg2,arg3,......*/){
var mySlice = Array.prototype.slice;
var save_args = mySlice.call(arguments,1)
return function (){
var newArgs = mySlice.call(arguments);
var args = save_args.concat(newArgs);
return fn.apply(null,args)
}
}
window.onload = function (){
var oUl = document.getElementById("ul");
var aLis = oUl.getElementsByTagName("li");
var iWidth = 100;
var iHeight = 100;
var iMargin = 10;
var iColNum = 3;
var newGetPosition = curry( getPosition , iWidth , iHeight , iMargin , iMargin , iColNum );
for( var i=0; i<aLis.length; i++ ){
//var p = getPosition( iWidth , iHeight , iMargin , iMargin , iColNum , i )
var p = newGetPosition(i)
aLis[i].style.top = p.top + "px";
aLis[i].style.left = p.left + "px";
}
}
</script>
</head>
<body>
<ul id="ul">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
</html>
到这里了,睡觉去zzzZZZZ....
函数Curry化的更多相关文章
- 转:python中函数curry化
1 柯里化(Currying) 一个函数有多个参数,我们希望能固定其中几个参数的值. from functools import partial def foo(a,b,c): return a+b+ ...
- Curry化函数
<script> function fn(){ var i, rult = 0, len = arguments.length; for (i=0;i<len ;i++ ) { ru ...
- ♫【模式】Curry化
/** * 当发现正在调用同一个函数,并且传递的参数绝大多数都是相同的, * 那么该函数可能是用于Curry化的一个很好的候选参数 */ ;(function() { function add(x, ...
- scala学习手记25 - Curry化
curry翻译为中文就是咖喱.意为使用curry可以让代码更有味道. scala里的curry化可以把函数从接收多个参数转换成接收多个参数列表.也就是说我们要编写的函数不是只有一个参数列表,这个参数列 ...
- React 应用设计之道 - curry 化妙用
使用 React 开发应用,给予了前端工程师无限"组合拼装"快感.但在此基础上,组件如何划分,数据如何流转等应用设计都决定了代码层面的美感和强健性. 同时,在 React 世界里提 ...
- JavaScript基础Curry化(021)
时候我们希望函数可以分步接受参数,并在所有参数都到位后得到执行结果.为了实现这种机制,我们先了解函数在Javascript中的应用过程: 1. 函数的“应用”(Function Application ...
- (MTT)连续能量函数最小化方法
(MTT)连续能量函数最小化方法 Multitarget tracking Multi-object tracking 连续能量函数 读"A.Milan,S. Roth, K. Schind ...
- Scalaz(3)- 基础篇:函数概括化-Generalizing Functions
Scalaz是个通用的函数式编程组件库.它提供的类型.函数组件都必须具有高度的概括性才能同时支持不同数据类型的操作.可以说,scalaz提供了一整套所有编程人员都需要的具有高度概括性的通用函数,它是通 ...
- vue render函数 函数组件化
之前创建的锚点标题组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法,它只是一个接受参数的函数 在这个例子中,我们标记组件为functional,这意味它是无状态(没有data), ...
随机推荐
- 2.4使用属性在 ASP.NET Web API 2 路由创建一个 REST API
Web API 2 支持一种新型的路由,称为属性路由.属性路由的一般概述,请参阅属性路由 Web API 2 中.在本教程中,您将使用属性路由创建一个 REST API 集合的书.API 将支持以下操 ...
- Java 中的内存泄露
1.当你完成对流的读写时,应该通过调同close方法来关闭它,这个调用会释放掉十分有限的系统资源,否则,如果一个应用程序打开了过多的流而没有关闭,那么系统资源将被耗尽.
- dos 操作显示 > nul 2>nul
1>nul 屏蔽操作成功显示的信息,但是出错还是会显示(同 >nul)2>nul 屏蔽操作失败显示的信息,但是成功还是会显示>nul 2>nul 就是正确的错误的一起屏蔽 ...
- C#静态常量和动态常量的区别
C#拥有两种不同的常量:静态常量(compile-time constants)和动态常量(runtime constants).它们有不同的特性,错误的使用不仅会损失效率,还可能造成错误.相比之下 ...
- Other Linker Flags到底是什么
一.问题描述 在项目开发中用到百度地图,有时候在工程中会报“方法找不到”的错误(unrecognized selector sent to instance). 二.问题分析 首先,要说明一下Othe ...
- Sass安装(windows版)
Sass安装(windows版) 在 Windows 平台下安装 Ruby 需要先有 Ruby 安装包,大家可以到 Ruby 的官网(http://rubyinstaller.org/download ...
- .NET LINQ 数据分组
数据分组 分组指将数据放入组中以便每个组中的元素共享公共特性的操作. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表达式语法 更多信息 GroupBy 对共享 ...
- Nginx与Apache的比较
Nginx与Apache的比较 Nginx相对于Apache的优点 轻量级.同样起web服务,比apache占用更少的资源和内存 抗并发.nginx处理请求是异步非阻塞,而apache则是阻塞型.在高 ...
- php 总结第一篇(望大家补充!谢谢)
/* 数组的常用函数 * * 数组的排序函数 * sort() * rsort() * usort() * asort() * arsort() * uasort() * ...
- CSS基础及选择器
CSS层叠样式表与表相分离.常用CSS2和CSS3. HTML引入CSS 1.行内样式 <div style="color:red"></div> 2.内部 ...