2012-07-29 37 views
1

我想實現一種在JavaScript中實現繼承的方法。首先我定義基類,如下所示:爲什麼我不能從內部重新定義函數的原型

function Person(name){ 
    name = name + "!"; //I want to reuse this code for initialization 

    this.getName = function(){ 
     return name; 
    }; 

    this.setName = function(_name){ 
     name = _name; 
    }; 
}; 

然後我定義子類。發生,我需要一種方法來調用基類的構造函數。理想情況下,我會從VipPerson構造函數中調用它,當我仍然有參考name param。但是,如果我從這一點做它根本不工作,如果我嘗試從基類訪問getName我得到一個錯誤VipPerson has no getName method

function VipPerson(name, vipLevel){ 
    this.getVipLevel = function(){ 
     return vipLevel; 
    }; 

    //the line below would not work! 
    //VipPerson.prototype = new Person(name); 
}; 

VipPerson.prototype = new Person(); //but this would. not ideal IMO 

的缺點爲我設置爲從VipPerson外的原型是我失去了參數的任何引用被傳遞。

有沒有一種優雅的方式來解決這個問題?我想要這個乾淨的界面:

var foo = new Person("Foo"); 
console.log(foo.getName()); 

var bar = new VipPerson("Bar", 100); 
console.log(bar.getName()); //error 
console.log(bar.getVipLevel()); 

回答

0

您是否嘗試過這種做法?

function VipPerson(name, vipLevel){ 
    this.__proto__ = new Person(name); 

    this.getVipLevel = function(){ 
     return vipLevel; 
    }; 
}; 
+0

請注意,就是這樣,你沒有做繼承,就像問題似乎問:'var vp = new VipPerson(「John」);警報(vp instanceof Person)// false'。爲了獲得適當的繼承,您需要正確設置'prototype'。詳情請參閱我的回答。 – ZER0 2012-07-29 20:16:12

+0

是的,你是正確的@ZERO。雖然你答案實現繼承,但它可能會導致一個非常大的錯誤。當你將函數「call」作爲參數傳遞給「this」時,你正在複製VipPerson中Person的所有屬性。更改原型,將在原型中創建相同的屬性。 – 2012-07-30 11:21:34

+0

這不是一個錯誤,這就是繼承的作用。如果'Person'有一個'foo'方法,我也想'VipPerson'。構造函數動態擴展對象的事實與我的提議或繼承無關,而是與原始代碼有關,我明確表示不應該這樣做。最好使用'prototype'來定義方法,但是在這種情況下你不能真正擁有「私有」(通常在JS中它很好)。 '__proto__'的新編輯不是標準的,不能用於交叉瀏覽。 – ZER0 2012-07-30 15:50:17

1

它排序的工程,當你從構造函數中設置原型,但它不會做你真正想要的。由於原型對象的設置直到您已經運行構造函數爲止,所以在第一次調用「VipPerson」構造函數時第一個新創建的對象(this)將不會被正確「連線」。

但是,如果您再次調用構造函數,則會注意到原型在那裏並且「.getName()」有效。

請注意,除非您希望所有「人員」對象共享相同的名稱,否則不會以任何方式工作。應該設置「Person」,使得「setName()」更新this.name而不是閉包中的變量。只有一個「人」實例全部「VipPerson」實例—即爲實例化的原型對象。

+0

嘿@Pointy,你可以看看@Geraldo Ferraz的答案嗎?通過使用'call'方法,我可以爲每個VipPerson擁有不同的Person ...你覺得怎麼樣? – renatoargh 2012-07-29 17:20:57

+0

那麼,你並沒有一個單獨的「Person」對象,你只需使用「Person」構造函數來填充新構建的「VipPerson」的屬性。因此,這種方法確實沒有單獨的原型對象。如果它對你有用,但沒有什麼問題。 *編輯* - 我會推薦*不*設置原型屬性; ZERO的答案更好。 – Pointy 2012-07-29 17:22:20

2
function VipPerson(name, vipLevel){ 
    Person.call(this, name); 

    this.getVipLevel = function(){ 
     return vipLevel; 
    }; 
}; 

VipPerson.prototype = Object.create(Person.prototype); 

參見:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create/

不過,我會避免創建閉包只是爲了讓 「士兵」 的變量,除非有特定的安全問題。 JavaScript是一種基於OOP原型的動態語言,不應該像私有成員那樣使用基於類的語言。

我建議你閱讀文章這樣的一個:https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript

相關問題