码迷,mamicode.com
首页 > 编程语言 > 详细

javascript之反柯里化(uncurrying)

时间:2018-02-15 19:14:27      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:通过   .sh   this   读写   post   模式   UI   fun   span   

在JavaScript中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型语言的特点。可以通过反柯里化(uncurrying)函数实现,让一个对象去借用一个原本不属于他的方法。

通常让对象去借用一个原本不属于它的方法,可以用call和apply实现,如下

 

更常见的场景之一是让类数组对象去借用Array.prototype的方法;

(function(){
    Array.prototype.push.call(arguments,4)
    console.log(arguments);//[1, 2, 3, 4]
})(1,2,3)

扩展:为什么类数组对象能够借用数组的方法呢?不妨理解下V8的引擎源码,就以Array.prototype.push为例:

function ArrayPush() {
  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");
  var array = TO_OBJECT(this);
  var n = TO_LENGTH_OR_UINT32(array.length);
  var m = %_ArgumentsLength();
  .......
  for (var i = 0; i < m; i++) {
    array[i+n] = %_Arguments(i);
  }
  var new_length = n + m;
  array.length = new_length;
  return new_length;
}

通过这段代码大致可以看出,Array.prototype.push实际上是一个属性复制的过程,把参数按照下标依次添加到被push的对象上面,顺便修改了这个对象的length属性,这个对象到底是数组还是类数组并不重要。从源码可以看出,只要对象本身可以存取属性,且length属性可读写,就可以借用Array原型的push方法。

 

这样一来,方法中用到this的地方,就不在局限原本的对象,而是加以泛化并得到更广的适用性。那么有没有办法把泛化this的过程提取出来呢?那么反柯里化(uncurrying)就是解决这个问题的。反科里化(uncurrying)的话题来自JavaScript之父Brendan Eich在2011年发表的一篇文章,以下代码是实现方式之一:

Function.prototype.uncurrying = function() {
  var self = this;
  return function() {
    var obj = Array.prototype.shift.call(arguments);
    return self.apply(obj, arguments);
  };
};

然后就可以定义一个push函数,更加简洁和明了的实现了一个不在局限于数组的push方法。如下:

var push = Array.prototype.push.uncurrying();
(function(){
    push(arguments,4);
    console.log(arguments);//[1,2,3,4]
})(1,2,3)

除了刚刚的一种反柯里化实现,还有另一种实现方式:

Function.prototype.uncurrying = function() {
  var self = this;
  return function() {
    return Function.prototype.call.apply(self,arguments)
  };
}
参考书籍:javascript设计模式与开发实践

 

javascript之反柯里化(uncurrying)

标签:通过   .sh   this   读写   post   模式   UI   fun   span   

原文地址:https://www.cnblogs.com/dupd/p/8449711.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!