组合继承
综合了原型链和盗用构造函数,将两者优点结合,使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性,这样既可以把方法定义在原型上实现重用,又可以让每个实例都有自己的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function SuperType(name){ this.name=name; this.colors=["red","blue","green"]; } SuperType.prototype.sayName=function(){ console.log(this.name); } function SubType(name,age) { SuperType.call(this,name); this.age=age; }
SubType.prototype=new SuperType(); SubType.prototype.sayAge=function(){ console.log(this.age); } let instance1=new SubType('Ann',29); instance1.colors.push("balck"); console.log(instance1.colors); instance1.sayName(); instance1.sayAge();
let instance2=new SubType("Greg",27); console.log(instance2.colors); instance2.sayName(); instance2.sayAge();
|
原型式继承
1 2 3 4 5 6 7 8 9 10 11 12 13
| function object(o){ function F(){}; F.prototype=o; return new F(); } let person={ name:"Ann", friends:["Mary","Harry","Van"] } let anotherPerson=object(person); anotherPerson.friends.push("Mike"); console.log(person.friends);
|
object()函数创建一个临时构造函数,将传入对象赋值给这个构造函数原型,然后返回这个临时类型的一个实例。本质上,object()是对传入的对象执行了一次浅复制,anotherperson.proto=person,如果person是构造函数,则anotherperson的[[Prototype]]将没有指向的prototype对象,也就无法通过prototype对象找到constructor进而使用construcor上面的方法和属性
这里的object函数相当与object.create()
1 2 3 4 5 6 7 8
| let person={ name:"Ann", friends:["Mary","Harry","Van"] } let anotherPerson=object。create(person); anotherPerson.friends.push("Mike"); console.log(person.friends);
|
原型式继承适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合。
寄生式继承
与原型式继承比较接近的一种继承方式是寄生式继承
1 2 3 4 5 6 7 8 9 10 11 12 13
| function createAnother(original){ let clone=Object.create(original); clone.sayHi=function(){ console.log("hi"); } return clone; } let person={ name:"Ann", friends:["Mary","Harry","Van"] } let anotherPerson=createAnother(person); anotherPerson.sayHi();
|
寄生式继承同样适合主要关注对象,而不在乎类型和构造函数的场景。痛过寄生式继承给对象添加函数会导致函数难以重用,与构造函数模式类似。
寄生式组合继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function inheritPrototype(subType,superType){ let prototype=Object.create(superType.prototype); prototype.constructor=subType; subType.prototype=prototype; } function SuperType(name){ this.name=name; this.colors=["red","blue","green"]; } SuperType.prototype.sayName=function(){ console.log(this.name); } function SubType(name,age) { SuperType.call(this,name); this.age=age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge=function(){ console.log(this.age); } let instance1=new SubType('Ann',29); instance1.colors.push("balck"); console.log(instance1.colors); instance1.sayName(); instance1.sayAge();
|
另一种写法:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function SuperType(name){ this.name=name; this.colors=["red","blue","green"]; } SuperType.prototype.sayName=function(){ console.log(this.name); } function SubType(name,age) { SuperType.call(this,name); this.age=age; } SubType.prototype=Object.create(SuperType.prototype) SubType.prototype.constructor=Subtype
|
寄生式组合继承基本模式:
- 先创建父类原型的一个副本prototype
- 给prototype设置constructor属性为subType,增强对象,解决由于重写原型导致默认constructor丢失问题
- 将新创建的对象赋值给子类型的原型
只调用一次SuperType构造函数,效率最高