• javascript中的部分函数应用


    这篇文章写的很全面,不过也啰嗦:http://benalman.com/news/2012/09/partial-application-in-javascript/

    这篇文章是神级运用:http://osteele.com/sources/javascript/functional/

    绑定变量

    假设我们函数的部分参数已经固定,我们可以绑定这个参数,生成新的函数。

    // 一般函数
    function add(a, b) {
      return a + b;
    }
    
    // 特定情况的函数生成函数
    function makeAdder(a) {
      return function(b) {
        return a + b;
      };
    }
    
    // 特定函数
    var addOne = makeAdder(1);
    addOne(2);  // 3
    addOne(3);  // 4

    这里实现有两个重要的知识点,1.javascript允许函数访问外部变量(详细见javascript的闭包概念)。2.在javascript里,函数是可以将函数作为参数和返回值。

    绑定函数

    有时候我们需要绑定的不只是数值

    // 特定函数生成函数
    function bindFirstArg(fn, a) {
      return function(b) {
        return fn(a, b);
      };
    }
    
    // 一般函数
    function add(a, b) {
      return a + b;
    }
    
    // 特定函数
    var addOne = bindFirstArg(add, 1);
    addOne(2);           // 3
    addOne(3);           // 4

    由于函数可以作为参数,所以我们还可以实现函数绑定。

    部分函数应用

    部分函数应用可以解释为,将一个函数和它一些的参数绑定,然后返回一个新的函数,这个新函数继续接收剩下未绑定的参数。

    它与bind()方法原理上有些相似。

    注意:arguments 对象是一个类数组对象,当函数被调用时创建,只有在函数内部可以引用,它包括所有传入函数的参数。

    下面的部分应用函数,和使用实例。

    function partial(fn /*, args...*/) {
      var slice = Array.prototype.slice;
      var args = slice.call(arguments, 1);
    
      return function() {
        return fn.apply(this, args.concat(slice.call(arguments, 0)));
      };
    }

    下面是一个使用部分函数的例子:

    function add(a, b) {
      return a + b;
    }
    
    var addOne = partial(add, 1);
    addOne(2);           // 3
    addOne(3);           // 4

    下面分析一下是怎么工作的,为了将arguments转化为数组,就要使用数组的方法Array.prototype.slice,因为要使用两次,所以存储到slice缓存。partial函数将它的参数除第一个fn外,存储到args上,以便返回函数访问。当返回函数f调用时,再将新arguments对象转化为数组,利用数组方法Array.prototype.concat将两个数组合并,再利用apply调用fn,this是window,参数就是先前合并的参数,f的返回值就是fn的返回值。

    注意,他是利用apply可以接收数组的特性,将两个函数的参数转成数组再合并,以此保证绑定函数参数的长度可以不固定。

    也可以这样调用函数

    Function.prototype.partial = function() {
        var fn = this, args = Array.prototype.slice.call(arguments);
        return function() {
          return fn.apply(this, args.concat(
            Array.prototype.slice.call(arguments)));
        };
      };

    javascript中函数this指向调用它的对象。又函数的都是继承自函数的原型,所以可以String.prototype.split.partial()调用partial,而this指向的是split,这也就是partial的fn。

    如何跳跃式绑定参数值?

    Function.prototype.partial = function(){
        var fn = this, args = Array.prototype.slice.call(arguments);
        return function(){
          var arg = 0;
          for ( var i = 0; i < args.length && arg < arguments.length; i++ )
            if ( args[i] === undefined )
              args[i] = arguments[arg++];
          return fn.apply(this, args);
        };
      };

    思路就是,如果想跳跃的参数值为undefined,在返回函数f里,对先前值为undefined进行覆盖。

    部分函数应用到底有什么用?

    以下例子基于上面的partial。

    String.prototype.csv = String.prototype.split.partial(/,s*/);
     
      var results = "John, Resig, Boston".csv();
      alert( (results[1] == "Resig") + " The text values were split properly" );

    这里我们返回一个函数,保存到String.prototype.csv中,每个字符串默认就可以用csv进行字符串拆分。

    var delay = setTimeout.partial(undefined, 10);
     
      delay(function(){
        alert( "A call to this function will be temporarily delayed." );
      });

    这里我们返回一个默认延迟为10的函数,可以一定程度上简化调用。

    var bindClick = document.body.addEventListener
        .partial("click", undefined, false);
     
      bindClick(function(){
        alert( "Click event bound via curried function." );
      });

    简化事件监听。

    这个技术可以用于特定情况,构造简化的API。

  • 相关阅读:
    DOM是属性不是对象。
    jq的网络地址以及需注意的地方
    jq函数
    jq的ajax
    document.getElementById("a").getElementsByTagName("table")的实质
    setTimeout()和setInterval()技巧
    HTML的修改css的修改以及动画完成后,执行某个函数方法
    修改属性也就是表现形式的两种方式
    jq中的change事件
    SQL学习笔记2:SQL基础(DML)
  • 原文地址:https://www.cnblogs.com/winderby/p/4071433.html
Copyright © 2020-2023  润新知