• 函数柯里化


    与函数绑定紧密相关的主题是函数柯里化,它用于创建已经设置 好了一个或多个参数的函数。函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的参数。请看一下例子:

    function add(num1,num2){
    
      return num1+num2;
    
    };
    
    function curriedAdd(num2){
    
      return add(5,num2);
    
    };
    
    alert(add(2,3));//5
    
    alert(curriedAdd(3));//8

    这段代码定义了两个函数:add()curriedAdd()。候着本质上是在任何情况下第一个参数为5add()版本。尽管从技术上来说curriedAdd()并非柯里化的函数,但它很好地展示了其概念。

    柯里化函数通常由一下步骤动态创建:调用另一个函数并未它传入要柯里化的函数和必要参数。下面是创建柯里化函数的通用方式。

    function curry(fn){
    
      var args=Array.prototype.slice.call(arguments,1);
    
      return function(){
    
        var innerArgs=Array.prototype.slice.call(arguments);
    
        var finalArgs=args.concat(innerArgs);
    
        return fu.apply(null,finalArgs);
    
      }
    
    }

    Curry()函数的主要工作就是将被返回函数的参数进行排序。Curry()的第一个参数是要进行柯里化的函数,其他参数是要传入的值。为了获取第一个参数之后的所有参数,在argument对象上调用了slice()方法,并传入了参数1表示被返回的数组包含从第二个参数开始的所有参数。然后args数组包含了来自外部函数的参数。在内部函数中,创建了innderArgs数组用来存放所有传入的参数(又一次用到了slice())。有了存放来自外部函数和内部函数的参数数组后,就可以使用concat()方法将它们组合为finalArgs,然后使用apply()将结果传递给该函数。注意这个函数并没有考虑到执行环境,所以调用apply()时第一个参数是nullCurry()函数可以按一下方式应用。

    function add(num1,num2){
    
      return num1+num2;
    
    };
    
    var curriedAdd=curry(add,5);
    
    alert(curriedAdd(3));//8

    在这个例子中,创建了第一个参数绑定为5add()的柯里化版本。当调用curriedAdd()并传入3时,3会成为add()的第二个参数,同事第一个参数依然是5,最后结果便是8.你也可以像下面例子这样给出所有的函数参数:

    function add(num1,num2){
    
      return num1+num2;
    
    };
    
    var curriedAdd=curry(add,5,12);
    
    alert(curriedAdd());//17

    在这里,柯里化的add()函数两个参数都提供了,所以以后就无需再传递他们了。

    函数柯里化还常常作为函数绑定的一部分包含在其中,构造出更为复杂的bind函数,例如:

    function bind(fn,context){
    
      var args=Array.prototype.slice.call(arguments,2);
    
      return function(){
    
        var innerArgs=Array.prototype.slice.call(arguments);
    
        var finalArgs=args.concat(innerArgs);
    
        return fu.apply(context,finalArgs);
    
      }
    
    }

    curry()函数的主要更改在于传入的参数个数,以及它如何影响代码的结果。Curry()仅仅接收一个要包裹的函数作为参数,而bind()同时接受函数和一个object对象。这表示给被绑定的函数的参数是从第三个开始二不是第二个,这就要更改slice()的第一处调用。另一处更改是在倒数第3行将object对象传给apply()。当使用bind()时,它会返回绑定到给定环境的函数,并且可能它其中某些函数参数已经被设好。当你除了event独享再额外给事件处理程序传递参数时,这非常有用,例如:

    var handler={
    
      message:'Event handled',
    
      handleClick:function(name,event){
    
        alert(this.message+":"+name+":"+event.type);
    
      }
    
    }
    
    var btn=document.getElementById('my-btn');
    
    EventUtil.addHandler(btn,'click',bind(handler.handleClick,handler,'my-btn'));

    在这个更新过的例子中,handler.handleClick()方法接受了两个参数:要处理的元素的名字和event对象。作为第三个参数传递给bind()函数的名字,又被传递给了handler.handleClick(),handler.handleClick()也会同时接收event对象。

    ECMAScript5bind()方法也实现函数柯里化,只要在this的值之后再传入另一个参数即可。

    var handler={
    
      message:'Event handled',
    
      handleClick:function(name,event){
    
        alert(this.message+":"+name+":"+event.type);
    
      }
    
    }
    
    var btn=document.getElementById('my-btn');
    
    EventUtil.addHandler(btn,'click',handler.handleClick.bind(handler,'my-btn'));

    javaScript中的柯里化函数和绑定函数提供了强大的动态函数创建功能。使用bind()还是curry()要根据是否需要object对象响应来决定。它们都能用于创建复杂的算法和功能,当然两者都不应滥用,因为每个函数都会带来额外的开销。

     

    参考:《javaScript高级程序设计(第3版)

  • 相关阅读:
    就没有我遇不到的报错!java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/filter/Filter
    【HBase】通过Bulkload批量加载数据到Hbase表中
    【HBase】HBase和Hue的整合
    【HBase】协处理器是什么?又能干什么?怎么用?
    【HBase】带你了解一哈HBase的各种预分区
    【HBase】快速了解上手rowKey的设计技巧
    【HBase】HBase和Sqoop整合
    【HBase】快速搞定HBase与Hive的对比、整合
    hive元数据报错?试了很多方法都没辙?也许你漏了这一步
    【HBase】HBase与MapReduce集成——从HDFS的文件读取数据到HBase
  • 原文地址:https://www.cnblogs.com/wangdan0915/p/8274603.html
Copyright © 2020-2023  润新知