JS 繼承(三)寄生組合式繼承

JS 繼承(三)寄生組合式繼承

JS 繼承(二)中說(shuō)了組合繼承的模式,這種模式看起來(lái)似乎不錯(cuò)的樣子,那么它有什么缺點(diǎn)呢?

缺點(diǎn):父類的構(gòu)造函數(shù)運(yùn)行了兩遍,并且不能多繼承。

第一遍,把父類的實(shí)例賦值給子類的prototype屬性,目的是讓子類的實(shí)例繼承父類原型對(duì)象的方法。

第二遍,實(shí)例化子類的時(shí)候,new Man()會(huì)執(zhí)行Man的構(gòu)造函數(shù),而Man構(gòu)造函數(shù)里面有Person.call(this,...)語(yǔ)句,導(dǎo)致Person構(gòu)造函數(shù)執(zhí)行第二次,它的目的是為了給每個(gè)子類實(shí)例對(duì)象添加屬性。

為了更優(yōu)化組合繼承的方式,又發(fā)明了一種新的繼承方法:寄生組合式繼承。

它的目的是去掉第一遍父類構(gòu)造函數(shù)的執(zhí)行,只保留第二次的。

那么怎么把父類的原型對(duì)象給子類呢?

簡(jiǎn)單,把父類的原型對(duì)象拷貝一份,再把拷貝賦值給子類構(gòu)造函數(shù)的prototype屬性。

所以寄生組合繼承并不是使用原型鏈的原理達(dá)成繼承效果的,而是借用構(gòu)造函數(shù) + 拷貝對(duì)象的方式實(shí)現(xiàn)繼承。

代碼:

function Person (name,age) {
  this.name = name;
  this.age = age;
  this.friends = ['LiLei','HanMeiMei'];
  console.log('call this:', this)
}

Person.prototype.sayWords = function(des) {
  console.log(des+' say words:', this.name,this.age, this.friends.toString());
}

function Man (name, age) {
  this.name = name;
  Person.call(this,name, age);
}

function inert (SubClass, SuperClass) {
  let protoCopy = Object.assign({},SuperClass.prototype);
  protoCopy.constrouctor = SubClass;
  SubClass.prototype = protoCopy;
}

inert(Man, Person);

let m1 = new Man('tom', 12);
m1.friends.push('Green');

m1.sayWords("Person -> tom 1");

console.log("m1:", m1);
console.log("m1.__proto__:",m1.__proto__);

console.log('----------------')

let m2 = new Man('LiLei',13);
m2.sayWords("Person -> LiLei 2");

console.log("m2:", m2);
console.log("m2.__proto__:",m2.__proto__);

很明顯,這樣拷貝對(duì)象會(huì)導(dǎo)致同樣的屬性方法會(huì)有兩套,父類的原型對(duì)象一套,子類的原型一套,但是優(yōu)點(diǎn)也明顯,因?yàn)槭强截悓?duì)象屬性的方式繼承,所以它可以多繼承。
代碼如下:

function Person (name,age) {
  this.name = name;
  this.age = age;
  this.friends = ['LiLei','HanMeiMei'];
  console.log('call this:', this)
}

Person.prototype.sayWords = function(des) {
  console.log(des+' say words:', this.name,this.age, this.friends.toString());
}

function Teacher (subject) {
  this.subject = subject;
}

Teacher.prototype.sayWords = function() {
  console.log("I am a teacher.", this.subject);
}

Teacher.prototype.subjectFuc = function () {
  console.log('subject:',this.name, this.subject);
}

function Man (name, age, subject) {
  this.name = name;
  Person.call(this,name, age);
  Teacher.call(this, subject);
}

function inert (SubClass, SuperClass) {
  let protoCopy = Object.assign(SubClass.prototype,SuperClass.prototype);
  console.log('protoCopy是拷貝一個(gè)SuperClass.prototype對(duì)象:',!(protoCopy == SuperClass.prototype), protoCopy);
  protoCopy.constrouctor = SubClass;

  SubClass.prototype = protoCopy;
}

inert(Man, Person);
inert(Man, Teacher);

let m1 = new Man('tom', 12, 'Math');
m1.friends.push('Green');

m1.sayWords("Person -> tom 1");

console.log('----------------')

let m2 = new Man('LiLei',13, 'chinese');
m2.sayWords("Person -> LiLei 2");
m2.subjectFuc();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容