JS 继承(三)寄生组合式继承

JS 继承(三)寄生组合式继承

JS 继承(二)中说了组合继承的模式,这种模式看起来似乎不错的样子,那么它有什么缺点呢?

缺点:父类的构造函数运行了两遍,并且不能多继承。

第一遍,把父类的实例赋值给子类的prototype属性,目的是让子类的实例继承父类原型对象的方法。

第二遍,实例化子类的时候,new Man()会执行Man的构造函数,而Man构造函数里面有Person.call(this,...)语句,导致Person构造函数执行第二次,它的目的是为了给每个子类实例对象添加属性。

为了更优化组合继承的方式,又发明了一种新的继承方法:寄生组合式继承。

它的目的是去掉第一遍父类构造函数的执行,只保留第二次的。

那么怎么把父类的原型对象给子类呢?

简单,把父类的原型对象拷贝一份,再把拷贝赋值给子类构造函数的prototype属性。

所以寄生组合继承并不是使用原型链的原理达成继承效果的,而是借用构造函数 + 拷贝对象的方式实现继承。

代码:

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__);

很明显,这样拷贝对象会导致同样的属性方法会有两套,父类的原型对象一套,子类的原型一套,但是优点也明显,因为是拷贝对象属性的方式继承,所以它可以多继承。
代码如下:

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是拷贝一个SuperClass.prototype对象:',!(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();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。