浅谈JS中的反柯里化(uncurrying)

  

<强>反柯里化
  

  

相反,反柯里化的作用在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用。
  

  

即把如下给定的函数签名,

        obj。func (__arg1、最长)      

转化成一个函数形式,签名如下:

        func (obj, __arg1最长)      

这就是反柯里化的形式化描述。

  

例如,下面的一个简单实现:

        Function.prototype。uncurrying=function () {   var=这个;   返回函数(){   Function.prototype.call返回。应用(参数);   }   };      函数sayHi () {   返回“Hello”+。值+ " " + [].slice.call(参数);   }   var sayHiuncurrying=sayHi.uncurrying ();   console.log (sayHiuncurrying({值:‘世界’},“哈哈哈”));   之前      

解释:   

      <李> uncurrying是定义在函数的原型上的方法,因此对所有的函数都可以使用此方法。调用时候:sayHiuncurrying=sayHi.uncurrying(),所以uncurrying中这个指的向的是sayHi函数;(一般原型方法中的这个不是指向原型对象原型,而是指向调用对象,在这里调用对象是另一个函数,在javascript中函数也是对象)   <李>调用。应用(参数),把这个设置为调用方法的上下文,然后将参数传给调用方法,前文的例子,这实际指向sayHi,所以调用sayHiuncurrying (__arg1,最长,…)相当于sayHi。调用(__arg1、最长,…);李   <李> sayHi。调用(__arg1、最长,…),叫函数把__arg1当做sayHi的上下文,然后把最长,…等剩下的参数传给sayHi,因此最后相当于arg1.sayHi(最长,…);李   <李>因此,这相当于sayHiuncurrying (obj, args)等于obj.sayHi (args)。   
  

最后,我们反过来看,其实反柯里化相当于把原来sayHi (args)的形式,转换成了sayHiuncurrying (obj, args),使得sayHi的使用范围泛化了。更抽象地表达,uncurryinging反柯里化,使得原来x.y (z)调用,可以转成y (x, z)形式的调用。假设x '为x或者其他对象,这就扩大了函数的使用范围。

  

<强>通用反柯里化函数
  

  

上面例子中把uncurrying写进了原型,这不太好,我们其实可以把uncurrying单独封装成一个函数;

        var uncurrying=函数(fn) {   返回函数(){   var args=[] .slice.call(参数,1);   返回fn.apply(参数[0],args);   }   };      

上面这个函数很清晰直接。
  

  

使用时调用uncurrying并传入一个现有函数fn,反柯里化函数会返回一个新函数,该新函数接受的第一个实参将绑定为fn中这样的上下文,其他参数将传递给fn作为参数。

  

所以,对反柯里化更通俗的解释可以是函数的借用,是函数能够接受处理其他对象,通过借用泛化,扩大了函数的使用范围。

  

所以uncurrying更常见的用法是对Javascript内置的其他方法的借调而不用自己都去实现一遍。

  

文字描述比较绕,还是继续看代码:

        var测试=癮, b, c”;   console.log (test.split (", "));      var=uncurrying分裂(String.prototype.split);//(a, b, c的)   console.log(分裂(测试','));//(a, b, c的)      之前      

=uncurrying分裂(String.prototype.split)给uncurrying传入一个具体的fn,即String.prototype。分裂,分裂函数就具有了String.prototype。分裂的功能,函数调用分裂(测试”、“)时,传入的第一个参数为分裂执行的上下文,剩下的参数相当于传给原String.prototype。分裂函数。

  

再看一个例子:

        美元var={};   console.log ($ .push);//定义   var pushUncurrying=uncurrying (Array.prototype.push);   美元。推动=函数(obj) {   pushUncurrying (obj);   };   美元.push('第一次');   console.log ($ . length);//1   console.log ($ [0]);//第一个   console.log ($ .hasOwnProperty(长度));//正确的   之前      

这里模仿了一个“类似jquery库”实现时借用数组的推动方法。我们知道对象是没有推动方法的,所以console.log (obj.push)返回未定义,可以借用数组来处理,由原生的数组方法(js引擎)来维护伪数组对象的长度属性和数组成员。

  

同样的道理,我们还可以继续有:

        var indexof=uncurrying (Array.prototype.indexOf);   美元。indexOf=函数(obj) {   返回indexof (obj);   };   .push美元(“第二”);   console.log ($ .indexOf('第一次'));//0   console.log ($ .indexOf('第二'));//1   console.log ($ .indexOf('第三'));//1   

浅谈JS中的反柯里化(uncurrying)