在 Javascript 中递归调用"parent"构造函数?



我正在开发一个网络应用程序,该应用程序具有通过基于原型的继承创建的类层次结构之类的东西。我们不断向一个共同的祖先"类"添加功能,因此它的构造函数签名不断扩展。

每次更改祖先的签名时,我们还必须将更改传播到后代的构造函数。这显然是一个可维护性问题,所以我创建了一个函数,该函数从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 最终将在无限循环中调用自己。

如果我将 parentConstructor 字段与构造函数对象一起存储(而不是在原型中),我将不得不传入当前调用函数。这将使线路调用与周围的函数超级紧密耦合,这是我试图避免的。

因此,有谁知道更好的方法吗?

几天前我问了一个相关的问题,Kamyar Nazeri的回答对我帮助很大。

避免问题的方法是在定义新构造函数的闭包中定义_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()提供填充程序。我发现这个 ECMAScript 5 填充程序很有帮助。我通常只拉出我正在使用的垫片。

最新更新