函数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) ) //7

上面的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....

时间: 2024-11-05 14:38:30

函数Curry化----对不起,我有代码洁癖的相关文章

函数Curry化

Curry化技术是一种通过把多个参数填充到函数体中,实现将函数转换为一个新的经过简化的(使之接受的参数更少)函数的技术 写个例子,该函数的作用是改变一个div的样式 function changeStyle (obj,json){ for(var attr in json){ obj.style[attr] = json[attr] } } 假如我接下来可能需要大量的针对某一个元素进行样式改变,这时候 function changeStyle(obj,json){ if(typeof json

我可能有代码洁癖了

XX 的 前端代码真是不敢恭维 成堆的全局变量    随意的交互代码    杂乱的注释    坑爹的命名方式    过时的隐藏 input 埋点  为了装逼而存在的入口函数    功能一样的不封装     一排排的行内样式...      ( ...... ) 本来那都不是事,眼不见心不烦的无所谓,但是出了问题他自己不搞要领导推给我...( 公司老油条:太极高手       装傻领导:大合唱领队     难怪有些人上了年纪就说要转行啥的,不思进取,无原则推脱,活该被淘汰   ) 技术难题我是愿意

不使用ASP.NET服务器端控件(包括form表单不加runat=&quot;server&quot;)来触发.cs里的事件(方法),(适用于有代码洁癖者)。

很多时候,我们使用服务器端控件写出的代码,会给我们生成一些很多我们看不懂的代码(初学者),但是有时候我们并不需要这些代码(业务需求不同),对于生成的一些代码感到多余.所以我就开始想,有没有一种可能:不使用服务器端控件(包括form表单不加runat="server"属性)来触发后台写的某一个方法或事件(ASP.NET的事件实际上是使用事件机制来驱动的).经过测试是可以的. 原理:使用反射驱动方法. 步骤:    1.手写一个提交表单的js函数(可以使用asp.net的__dopostB

curry化函数

Curry化是一个转换过程,即我们执行函数的转换过程. function fn(x,y){        if(typeof y=="undefined"){            return function(y){                return x+y;            }        }        return x+y; } console.log(fn(10,5)) console.log(fn(10)(5))

JavaScript基础Curry化(021)

时候我们希望函数可以分步接受参数,并在所有参数都到位后得到执行结果.为了实现这种机制,我们先了解当函数在Javascript中的应用过程: 1. 函数的“应用”(Function Application) 在 函数化程序语言中,函数(Function)不是被调用(invoked)或被执行(called)的,而是被应用的(applied).在 Javascript中,函数是一个对象,因此它也可以被“应用”: Function.prototype.apply().下面就是一个例子: // defin

函数颗粒化 参数截取并传递

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script> /*----函数颗粒化就是函数参数截取,并合并参数-----*/ // 在这个函数中进行add函数所需参数的截取,用到的函数slice,call,apply function curry(fn){ //截取第一个参数 var firstAgu = A

js curry化

第一篇文竟然是curry开始-- 柯里化是什么(抄的):柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数. 柯里化的作用感觉上就是把函数分成多段来完成,也许可以方便测试吧但是至少,可以减少重复的参数 最简单的例子function curry() {    return function (a) {        return function (b) {            return a+b+5; }

逻辑函数的化简 【数字电路】

逻辑函数的化简 先补点各种门的 basic knowledge NAND 与非 NOR或非 XOR异或 XNOR 同或 对于同或,异或之前一直没搞明白....那个该死的标记老是混淆,也不知道为嘛标记的发明人为嘛要那么标记 ...现在知道了XOR...所以异或的标记是一个圈中间一把×             化简: 上面预设的ABCD的值输出结果是1 至于化简过程是为嘛...这个就是一步步化简....各种求并消项 切记!不要搞这种傻事! 然后就是另外一个很重要的化简方法--卡诺图 将n变量的全部最

巧用php中的array_filter()函数去掉多维空值的代码分享

在我们开发过程中,判断数组为空时你会想到什么方法呢?首先想到的应该是empty函数,不过直接用empty函数判断为空是不对的,因为当这个值是多维数的时候,empty结果是有值的 其实我们可以利用array_filter函数轻松去掉多维空值,而数组的下标没有改变,下面是举例用法: <?php $array = array( 0 => 'nicegy', 1 => false, 2 => 1, 3 => null, 4 => '', 5 => 'http://www.