2017-10-19 83 views
1

我目前正在嘗試使用JavaScript中的原型來創建類繼承,我理解如何在下面的簡單示例中工作。JavaScript繼承與父構造函數參數

var Person = function(){ 
    var name = "Steve"; 
} 

var Employee = function(){ 
    var company = "Stack Overflow"; 
} 

Employee.prototype = new Person; 

var employee1 = new Employee(); 

但現在假設我要添加參數的構造函數,這樣我創建的對象,我可以設置的值。所以更新的代碼是這樣的:

var Person = function(initName){ 
    var name = initName; 
} 

var Employee = function(initName, initCompany){ 
    //How can I use initName to set the value in the prototype class? 

    var company = initCompany; 
} 

Employee.prototype = new Person; 

var employee1 = new Employee("Bob", "Intel"); 

我怎麼能調用到人構造函數的名字嗎?在C#中(我最熟悉的語言),你可以簡單地調用基礎構造函數,並通過必要的參數,但似乎並沒有在javascript中有相同的模式。

供參考,這是它可能看起來像在C#:

public class Person 
{ 
    string name; 

    public Person(string initName) 
    { 
     name = initName; 
    } 
} 

public class Employee : Person 
{ 
    string company; 

    public Employee(string initName, string initCompany) : base(initName) 
    { 
     company = initCompany; 
    } 
} 

var employee1 = new Employee("Bob", "Intel"); 

免責聲明:正如你所看到的,我主要是一個面向對象編程,但我目前在JavaScript工作,所以一些我從JavaScript的角度來看可能是非感性的,隨時挑戰我的假設是必要的。

+0

看到這個任務[https://stackoverflow.com/questions/4152931/javascript-inheritance-call-super-constructor-or-use-prototype-chain)離子。它擁有你正在尋找的所有東西 –

+0

請參閱[Answer](https://stackoverflow.com/questions/4152931/javascript-inheritance-call-super-constructor-or-use-prototype-chain)。它擁有你正在尋找的一切。 –

回答

1

標準ES5及以下

對於示例的具體情況,headmax's answer做你需要什麼。然而,你在C#和其他語言中使用經典繼承模型可能會在一般意義上(即經典繼承)做到這一點,但這與JavaScript Prototype模型的相同方式是不可能的。你也許可以得到最接近使用組成,就像這樣:

var Person = function(initName){ 
    var name = initName; 
} 

var Employee = function(initName, initCompany){ 
    var innerPerson = new Person(initName); 

    var company = initCompany; 
} 

var employee1 = new Employee("Bob", "Intel"); 

然後,添加任何功能,你想上鏡或擴展Person類必須實現爲直通Employee類來實現,即。在內部Person對象中調用相應的函數。無可否認,這遠非實際的繼承,但它可以近似於多態性之類的行爲。

編輯

嗯,這是我以前關於完全忘了,但你可以使用call()apply()真正實現更多的繼承行爲一點。使用電話或應用可以讓你在指定的上下文中運行的功能(包括對象的構造函數),這樣你就可以在孩子的上下文中運行的父類的構造,就像這樣:

var Person = function(initName){ 
    var name = initName; 
} 

var Employee = function(initName, initCompany){ 
    Person.call(this, initName); 
    var innerPerson = new Person(initName); 

    var company = initCompany; 
} 

var employee1 = new Employee("Bob", "Intel"); 

但是,如果你想能夠訪問Employee構造函數中的name屬性和您在Employee中定義的任何其他函數,您需要將名稱的作用域可見性從var name = ...更改爲this.name = ...,以便在正在構建的對象的作用域中可見(這是this引用),而不是綁定到構造函數的作用域。有關所有此類應用的最佳示例,請參見here

ES6

由於採用了2015年的ECMAScript的,你現在可以在包裹語法糖,看起來更像是經典的繼承類定義。但是你必須記住,這仍然是在原型繼承下實現的,所以當JavaScript引擎實際執行代碼時,或者像Babel這樣的轉換器重寫它時,可能會出現類似於組合或call()/apply()的情況。

+0

好吧,聽起來我可能無法做我想做的事情,但感謝使用合成的替代方法。除非有人給出更好的答案,否則我現在不得不繼續這樣做。如果他們不這樣做,那麼我會將你的標記標記爲明天接受 –

+0

很高興的作文可能會有所幫助,但我更新了答案,以包含其他一些可能有用且更像繼承的方法 –

+0

優秀!使用Person.call並刪除「var innerPerson」這一行,並將範圍更改爲「this ...」而不是「var ...」使我比任何其他方法都更接近我想要的內容,並且基本上覆蓋了我想要的所有行爲(特別是因爲它允許我在子類中根據需要覆蓋函數和屬性) –

1

從ES6開始,JavaScript具有真實的類。他們不會在舊的瀏覽器(如Internet Explorer)中工作,但你可以寫爲

class Person { 
    constructor(name){ 
    this.name = name; 
    } 
} 

class Employee extends Person { 
    constructor(name, company) { 
    super(name); 
    this.company = company; 
    } 
} 
+0

是的,我希望我可以忽略舊的瀏覽器並使用這個實現,但不幸的是我必須支持舊版本的JS,所以我不能使用它。有沒有辦法在舊版本中做到這一點? –

+0

你可以看看babel repl,看看他們在做什麼。這不是最漂亮的,但它絕對是你想要的。 https://babeljs.io/repl/ –

+0

謝謝,這是一個有用的工具。這絕對是一團糟,所以我想我現在可能會堅持使用Ananth的方法,因爲它更容易維護 –