2012-04-27 55 views
1

我正在研究一个类似于通过基于原型的继承创建的类层次结构的web应用程序。我们不断地为一个共同的祖先“类”添加功能,所以它的构造函数签名不断扩展。在Javascript中递归调用“父”构造函数?

每次我们改变祖先的签名时,我们也必须将更改传播给下属的构造函数。这显然是一个可维护性问题,所以我创建了一个函数,用于从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字段与构造函数Functions对象(而不是原型)一起存储,则必须传入当前的调用函数。这将使线路调用超紧密耦合到周围的功能,我试图避免。

因此,有没有人知道任何更好的方法?

+0

你是什么意思“超紧密耦合到周围的功能”?从Child构造函数调用'this._super(Child,arguments)'应该没有问题,是吗? – Bergi 2012-04-27 11:08:27

+0

我只是希望能够将相同的代码行复制并粘贴到所有子构造函数中,而无需对其进行更改。就像我在Java中所做的一样... – 2012-04-27 15:05:45

回答

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会有所帮助。我通常只会拉出我正在使用的垫片。

+0

不幸的是,这是我一直试图避免的。我不喜欢使用函数构造对象的想法。它使得jsdoc非常尴尬,并使可怜的Eclipse变得困惑...... – 2012-05-18 13:41:03

+0

然后我认为你唯一的选择是使用父原型的实际名称。为什么_idea_使用函数来构造一个对象bug? – donut 2012-05-18 16:05:03

+0

我认为这种编程方式对于人类来说是相当不明确和令人困惑的,不仅如此,还有文档生成器和优化编译器。而且,通过这种编程,“类”对象都不是真正的类,所以'instanceof'运算符和许多其他工具将不起作用。 – 2012-05-23 08:45:47