2012-07-26 143 views
11

我正在設計一些JavaScript的類層次結構。到目前爲止它工作正常,但我看不出如何確定一個對象是否是父類的「實例」。例如:JavaScript的操作系統,instanceof和基類

function BaseObject(name){ 
    this.name = name; 

    this.sayWhoAmI = function(){ 
     console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1)); 
     console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2)); 
     console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject)); 
    }; 
} 
function Derivation1(){ 
    BaseObject.apply(this, ['first derivation']); 
} 
function Derivation2(){ 
    BaseObject.apply(this, ['second derivation']); 
} 

var first = new Derivation1(); 
var second = new Derivation2(); 

first.sayWhoAmI();日誌這樣的:

first derivation is a Derivation1 : true 
first derivation is a Derivation2 : false 
first derivation is a BaseObject : false 

second.sayWhoAmI();將這一情況記錄:

second derivation is a Derivation1 : false 
second derivation is a Derivation2 : true 
second derivation is a BaseObject : false 

我覺得同時firstsecond對象應該說他們的BaseObject實例。

我知道JavaScript可能不是爲此製作的,但我想知道是否有辦法實現這一點。

+6

只有調用'Base.apply(...)'不設置繼承。您必須正確設置原型。請參閱:http://jsfiddle.net/fkling/wJE6s/。也可以看看這個問題的解釋:http:// stackoverflow。com/questions/3145700/javascript-inheritance-instanceof-not-working?rq = 1 – 2012-07-26 01:37:29

+1

Felix你應該把它寫成答案,這正是我需要的,你的小提琴只是簡單地演示它。不要讓別人竊取你的聲譽! – Johnny5 2012-07-26 01:56:23

+0

同意他應該添加一個答案,但他可能不擔心提高他的代表0.01%! – jahroy 2012-07-26 02:06:57

回答

10

只調用Base.apply(...)不設置繼承。 .apply所做的就是將this設置爲第一個參數,沒有別的。調用父構造函數很重要,但這是不夠的。

你必須做的是正確設置原型鏈。也就是說,您必須將Derivation1.prototype設置爲從Base.prototype繼承的內容。

由於構造函數的每個實例從構造函數的原型繼承,你會看到這樣的代碼

Derivation1.prototype = new Base(); 

這是一個壞主意,你已經可以看到爲什麼:Base預計參數設置提供實例特定的屬性(在這種情況下爲name)。但我們不關心這些屬性,因爲我們稍後將它們初始化爲Base.apply(this, ...)的子構造函數。

所以,我們需要的是一個對象從Base.prototype繼承,幸運的是,ECMAScript的5定義一個函數,它可以做到這一點對我們(polyfill):

Derivation1.prototype = Object.create(Base.prototype); 

這將創建一個新的對象從Base.prototype繼承。現在,因爲你有一個新的對象取代了原來的原型,你必須設置constructor屬性,以便它正確地指向Derivation1

Derivation1.prototype.constructor = Derivation1; 

下面是一個完整的例子。還有看看this fiddlethis excellent answer by T.J. Crowder,這基本上解釋了相同的問題,但也許在一個更好的方式。


function BaseObject(name){ 
    this.name = name; 
} 

// move properties shared by all instances to the prototype! 
BaseObject.prototype.sayWhoAmI = function() { 
    console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1)); 
    console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2)); 
    console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject)); 
}; 

function Derivation1(){ 
    BaseObject.apply(this, ['first derivation']); 
} 

Derivation1.prototype = Object.create(BaseObject.prototype); 
Derivation1.prototype.constructor = Derivation1; 

// some useless method of the child "class" 
Derivation1.prototype.someOtherMethod = function() { 
    return 42; 
}; 

var first = new Derivation1(); 
first.sayWhoAmI();