在Javascript中递归调用“父”构造函数?

时间:2012-04-27 10:38:35

标签: javascript inheritance prototypal-inheritance

我正在开发一个类似于通过基于原型的继承创建的类层次结构的webapp。我们不断向共同的祖先“类”添加功能,因此它的构造函数签名不断扩展。

每次我们更改祖先的签名时,我们还必须将更改传播给后代的构造函数。这显然是一个可维护性问题,因此我创建了一个函数,它从arguments对象中提取父项的参数,并使用Function.apply()调用父项。

代码如下所示:

BaseClass.prototype._super = function(args) {
    args = Array.prototype.slice.call(args, this.constructor.length);
    this.parentConstructor.apply(this, args);
};

并像这样使用:

function Child(child_arg1, child_arg2 /*, implicit parent args */) {
    this._super(arguments);
}

(我不能使用arguments.caller.arguments,因为代码是严格模式。 this.parentConstructor由构建类层次结构的函数设置。)

不幸的是,这只适用于一个级别的继承:例如,如果A的父类B有自己的父类C,当B调用_super时,this.parentConstructor仍指向B,这意味着B最终会把自己称为无限循环。

如果我使用构造函数Functions对象(而不是原型)存储parentConstructor字段,我将必须传入当前的调用函数。这将使线路调用与周围功能紧密耦合,我试图避免这种情况。

那么有没有人知道更好的方法呢?

1 个答案:

答案 0 :(得分:0)

我几天前问过a related questionKamyar Nazeri's answer给了我很多帮助。

避免问题的方法是在闭包中定义_super,其中定义了新的构造函数,以便它始终引用正确的父对象。以下模式对我来说非常有效:

var BaseClass = 
{
   create: function() // Basically a constructor
   {
      var obj = Object.create({});

      obj.someProperty = "initial value based on arguments";

      return obj;
   };
};

var Child = (function buildChild(){
   var obj    = BaseClass.create("some value", "another argument")
     , _super = Object.getPrototypeOf(obj);

   // override BaseClass.create()
   obj.create = function()
   {
      var obj = _super.create.apply(this, arguments);

      // Child specific initializations go here

      return obj;
   };

   return obj;
})(); // note that this gets called right away

var c = Child.create("some argument", "another thing");

console.log(BaseClass.isPrototypeOf(c)); // true

请注意,对于旧版浏览器,您需要为Object.create()Object.getPrototypeOf()提供shims。我发现this ECMAScript 5 shim有帮助。我通常只拿出我正在使用的垫片。