2017-08-17 86 views
2

我想繼承類「EventEmitter」和預先定義的類「人」,這裏是代碼使用Javascript - 在ES6多重繼承,

class Person { 
    constructor(name, age) { 
     this.name = name; 
     this.age = age; 
    } 
    introduces() { 
     return `My name is ${this.name}. I am ${this.age} years old.`; 
    } 
}; 

\\here comes the mixin part 

function mix(...mixins) { 
    class Mix {} 
    for (let mixin of mixins) { 
     copyProperties(Mix, mixin); 
     copyProperties(Mix.prototype, mixin.prototype); 
    } 
    return Mix; 
} 

function copyProperties(target, source) { 
    for (let key of Reflect.ownKeys(source)) { 
     if (key !== "constructor" && key !== "prototype" && key !== "name") { 
      let desc = Object.getOwnPropertyDescriptor(source, key); 
      Object.defineProperty(target, key, desc); 
     } 
    } 
} 

我打算創建一個新類「PersonWithEmitter」 ,並且還調用構造象下面這樣:

class PersonWithEmitter extends mix(Person,EventEmitter){ 
    constructor(name,age){ 
     super(name,age) 
     \\do something else 
    } 

這裏談到的問題,當我創建「PersonWithEmitter」的新實例,這樣let someOne = new PersonWithEmitter("Tom",21),不會得到什麼,我什麼,在新的班級,我想使用this.namethis.age,這仍然是未定義的。 那麼,我該如何改變我的代碼,所以新類可以有其父方法,只有類「Person」的構造函數? 請原諒我破碎的英語。

+2

**不要完全用粗體**寫。 – zzzzBov

+0

爲什麼不使用現有的實現,如https://www.npmjs.com/package/event-emitter-mixin – loganfsmyth

+0

@loganfsmyth我認爲這個問題更多的是關於_why它不工作,而不是實現this_。顯然,執行這樣的事情不是問題,這是mixin在JS中的工作方式...在這裏... – somethinghere

回答

2

在很多情況下,JavaScript中的多重繼承指示了錯誤的設計決策。這可能會導致黑客行爲不符合他們的行爲。它的完成方式應該始終由特定的對象決定。在某些情況下,需要自己的屬性的淺拷貝,另一個應該遍歷整個原型鏈。 Composition over inheritance通常是更好的選擇。

上面的代碼中的問題是沒有調用類構造函數。 Mix有空的構造函數。這就是爲什麼PersonWithEmitter無法按預期工作的原因。

多個構造函數調用通常可以堆疊,如:

function Foo(...args) { 
    let _this = this; 
    _this = Bar.apply(_this, args); 
    _this = Baz.apply(_this, args); 
    return _this; 
} 

如果BarBaz是ES6類,因爲它包含了防止它被稱爲無new機制這是行不通的。在這種情況下,它們應該被實例:

function Foo(...args) { 
    copyProperties(this, new Bar(...args)); 
    copyProperties(this, new Baz(...args)); 
} 

靜態和原型屬性也可以被複制到Foo等中代碼所示的上方。

如果將案例縮小到Node.js EventEmitter,則可以像特例一樣處理。其實施是certain並且穩定。已知EventEmitter在構造函數中進行初始化,它有一個淺的原型鏈和屬性描述符。所以它可能應該是:

class Foo extends Bar { 
    constructor(...args) { 
    super(...args) 
    EventEmitter.call(this); 
    // or 
    // EventEmitter.init.call(this); 
} 
copyProperties(Foo.prototype, EventEmitter.prototype); 
+0

謝謝,問題解決了。我現在看到它的方式,我可以用兩種方法來實現,首先,我可以讓class Person繼承EventEmitter,並且它的確行得通。其次,我可以在上面編寫的構造函數中調用EventEmitter。 –

+0

不客氣。是的,在EventEmitter的情況下,兩個選項都有效。 – estus