2012-04-27 54 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