2011-07-05 45 views
5

我想在JS中「得到」繼承。 我剛剛發現了一個巧妙的方法來從一個對象的所有屬性基本上覆制到另一個:JS中的繼承:this.base = Class(); this.base()或...?

function Person(name){ 
    this.name="Mr or Miss: "+name; 

    this.introduce = function(){ 
    console.log("Hi, I am "+this.name); 
    } 
} 

function Employee(name,title){ 
    this.title=title; 

    this.base=Person; 
    this.base(name); 

} 

e = new Employee('tony', 'manager') 
e.introduce(); 

請注意,我有一個構造一個Person()類,並通過構造函數生成的屬性「名」。 關於這一點的好處還在於,員工在構造函數中也有名稱 - 並且瞧,它使用相同的參數創建Person對象。

如果我曾與 「原型」 的方式做到了這一點:

function Person(name){ 

    this.introduce = function(){ 
    console.log("Hi, I am "+this.name); 
    } 
} 

function Employee(name, title){ 
    this.name = name; /* ?!?!?!?!? I can't call the proper constructor here */ 
    this.title = title; 
} 
Employee.prototype= new Person(); /* ?!?!? NO NAME HERE..>? */ 
Employee.prototype.constructor = Employee; 


e = new Employee('tony', 'manager') 
e.introduce(); 

錯誤....現在該怎麼辦?我甚至無法完成這個:Employee中的this.name不能使用適當的Person構造函數來設置; Person對象的創建在繼承中只發生一次。

那麼...我錯過了什麼?我的第一個例子是「我的」辦法嗎?有沒有辦法與第二個例子有相同的結果?

幫助!

回答

9

這種原型繼承的往往是做這種方式:

function Parent() {} 

function Child() { 
    Parent.call(this); // call the constructor of the parent 
} 

var Constr = function() {}; 
Constr.prototype = Parent.prototype; 

Child.prototype = new Constr(); 
Child.prototype.constructor = Child; 

所以「絕招」是對Parent.prototype爲原型分配到一個空的功能,並設置該功能的一個新實例作爲Child原型。

這樣做是爲了讓延長Child.prototype沒有延伸Parent.prototype

您還必須在子構造函數中調用父項的構造函數。我想這是你努力的一部分。每個函數都有一個call[docs]apply[docs]方法,讓我們明確地設置元素this應該參考函數內部。

在您的例子,它看起來像:

function Employee(name,title){ 
    this.title=title; 

    Person.call(this, name); 
} 

不分配構造的實例的屬性。

在你的榜樣,this.base(name)作品,因爲通過分配構造的實例的屬性(並調用它這樣),this在函數內部指的是實例。


存在實現這種模式幾個庫,例如Google Closure library

goog.inherits = function(childCtor, parentCtor) { 
    /** @constructor */ 
    function tempCtor() {}; 
    tempCtor.prototype = parentCtor.prototype; 
    childCtor.superClass_ = parentCtor.prototype; 
    childCtor.prototype = new tempCtor(); 
    childCtor.prototype.constructor = childCtor; 
}; 
+0

我無法表達我對這個答案,我感激不盡...... – Merc

+0

我完全理解在谷歌關閉圖書館的功能(哇,我一定要得到的地方:d)但是!根據我的理解,當我創建派生類時,如果我想繼承內部屬性,則由我來決定,鍵入Parent.call(this);或Parent.call(這個名字) - 是嗎?難道你不是總想這麼做嗎? – Merc

+0

@Tony:我想你會的。但是,如果你有經典的繼承(比如Java),那麼如果覆蓋它,你還必須調用父類的構造函數。唯一的區別是在JavaScript中你基本上總是覆蓋構造函數,因爲這是我們如何模擬類。所以它實際上沒有什麼不同,也許更容易理解正在發生的事情。 –