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