2014-03-14 125 views
1

我有使用原型繼承JavaScript中像這樣的構造函數鏈:如何在原型鏈中找到構造函數的根構造函數?

var Test = function(){}; 
var Foo = function(){}; 
var Bar = function(){}; 
var Baz = function(){}; 
Bar.prototype = new Baz(); 
Foo.prototype = new Bar(); 
Test.prototype = new Foo(); 

我想編寫一個函數getRootConstructor(),使得

getRootConstructor(Test) === Baz. 

的目標是,我可以做

getRootConstructor(Test).prototype = new UniversalBaseConstructor(); 

所以我可以在不破壞原型鏈的情況下爲構造函數添加功能。這原來是非常不直觀的。

+0

由於你已經建立了繼承,所以'(new Test())。constructor === Baz'。 – RobG

回答

1

在OP,請注意:

var t = new Test(); 
t.constructor == Test; // false 
t.constructor == Baz; // true 

所以基礎構造函數由t.constructor給出。

然而,這是很常見的重新設置這樣的建築遺產時,使每個原型的構造屬性指向正確的構造函數(「修復」)的constructor屬性:

var Test = function(){}; 
var Foo = function(){}; 
var Bar = function(){}; 
var Baz = function(){}; 

Bar.prototype = new Baz(); 
Bar.prototype.consructor = Bar; 

Foo.prototype = new Bar(); 
Foo.prototype.constructor = Foo; 

Test.prototype = new Foo(); 
Test.prototype.constructor = Test; 

這意味着布拉德的getRootConstructor功能將不能作爲Constructor.prototype.constructor工作始終指向「真實」的構造和

getRootConstructor(Test) === Test; 

在在這種情況下,爲每個指向原型構造函數的原型添加一個_super(或類似的名稱)屬性也很常見,所以可以這樣找到基礎構造函數。

請注意,如果Brad的函數真的起作用,它將始終返回內置的Function對象,因爲它是所有函數的基礎構造函數。

+0

你是對的類與構造函數,所以我編輯了這個問題。如果您重新設置prototype.constructor,我的答案會中斷,但是否則它會起作用。 –

+0

* prototype *對象的* prototype *屬性在其關聯的構造函數創建時建立。因爲用特定構造函數中的實例替換該* prototype對象,並且不指定構造函數屬性,所以從鏈中任何構造函數創建的每個實例都將繼承「base」原型的構造函數,所以'anyInstance.constructor'和'anyConstructor .prototype.constructor'將引用基礎構造函數。所以不需要* getRootConstructor *函數。 :-) – RobG

+0

如果你想刪除對此類的引用,我將接受它作爲答案 –

2

如果您沒有設置函數的原型,他們有一個循環引用,使得F.prototype.constructor === F.你想要的功能的話,就是:

function getRootConstructor(T){ 
return T.prototype.constructor === T ? T : getRootConstructor(T.prototype.constructor); 
} 
+0

直到有人與(公共,可變)*構造函數混淆* ... – RobG

相關問題