第一種方式
/** * @函數名稱:copyProperties * @param * @作用:類的屬性和函數copy */ function copyProperties(target, source) { for (let key of Reflect.ownKeys(source)) { if ( key !== 'constructor' && key !== 'prototype' // && key !== 'name' // name 屬性允許繼承 ) { let desc = Object.getOwnPropertyDescriptor(source, key); Object.defineProperty(target, key, desc); } } } /** * @函數名稱:mixin * @param 類名 * @作用:實現多繼承 * @return:繼承後的類 */ export function mixin(...mixins) { class Mix { constructor() { for (let mixin of mixins) { copyProperties(this, new mixin()); // 拷貝實例屬性 } } } for (let mixin of mixins) { copyProperties(Mix, mixin); // 拷貝靜態屬性 copyProperties(Mix.prototype, mixin.prototype); // 拷貝原型屬性 } return Mix; } class Cat { name = 'cat'; // } class Dog { getName() { return this['name']; } } class Test extends mixin(Dog, Cat){}; var test = ()=> new Test(); // name屬性爲class關鍵字後面的類名 console.log(Test.name); // Test console.log(test.name); // test console.log(test().name); // cat console.log(test().getName()); // cat
第二種方式:通過修飾器實現
/** * 通過修飾實現混合繼承 * @param mixins */ export function mixins(...mixins) { return function (target) { const _mixins = mixin(...mixins); const instance = new _mixins(); Object.assign(target.prototype, instance); } } class Cat1 { _name = 'cat'; } class Dog1 { // 函數必須是等於這種屬性的形式來寫才能繼承 getName = function () { return this['_name']; } } // 不能繼承name屬性 且定義name時會報錯 @mixins(Cat1, Dog1) class Test1 {} var test1 = new Test1(); console.log(Test1.name); // Test1 console.log(test1._name); // Test1 console.log(test1['getName']()); // cat