基础知识点:1.原型链的读取规则;2.原型链中prototype和constructor的属性;3.原型链中prototype和constructor的指针指向。

1. 原型链继承

基本思想:是利用原型让一个引用类型继承另一个引用类型的属性和方法。

  1. function SuperType(){
  2. this.name = 'father'
  3. this.age = '45'
  4. }
  5. SuperType.prototype.getName = function(){
  6. console.log(this.name)
  7. }
  8. function SubType(){
  9. this.name = 'son'
  10. SuperType.call(this)
  11. }
  12. SubType.prototype = new SuperType()
  13. SubType.prototype.getAge = function (){
  14. console.log(this.age)
  15. }
  16. let subType = new SubType()
  17. console.log(subType)
  18. subType.getAge()
  19. subType.getName()

以上代码定义了两个类型:SuperType和SubType。每个类型分别有一个属性和方法。他们的主要区别是SubType继承了SuperType, 而继承是通过创建SuperType的实例,并将该实例赋给SubType.prototype实现的。 实现的本质是重写原型对象,代之以一个新类型的实例。
image.png
最终结果是 实例subType指向SubType的原型,SubType的原型又指向SuperType的原型。
注意:通过原型链实现继承时,不能使用对象字面量创建原型方法。因为这样做就会重写原型链。

  1. 实现了什么?

实现了继承超类的属性和方法。

  1. 原型继承时发生了什么?

在通过原型来实现继承时,原型实际上会变成另一个类型的实例。于是,原来的实例属性( new SuperType() )也就顺理成章地变成了现在的原型属性了。

  1. 原型链问题?

主要问题来自包含引用类型值的原型,引用类型值的原型属性会被所有实例共享; 而这也正是为什么要在构造函数中,而不是在原型对象中定义属性的原因。(原型链可以所有实例的属性和方法共享。有些属性值希望不同实例有不同的值,而只用原型链实现继承得不到想要的效果。需要配合构造函数来实现。)

借用构造函数继承

基本思想: 在子类型构造函数的内部调用超类型构造函数。(函数只不过实在特定环境中执行代码的对象,因此通过使用apply()和call()方法也可以在(将来)新创建的对象上执行构造函数。

  1. function SuperType(name){
  2. this.name = name;
  3. }
  4. function SubType(){
  5. SubType.call(this,'lis')
  6. this.age = 29;
  7. }
  8. var subtype = new SubType();
  9. console.log(subtype.name); //lis
  10. console.log(subtype.age); //29
  1. 实现了什么?

子类型中可以通过语法使用共享超类型的属性和方法。

  1. 借用构造函数的问题?

如果仅仅是借用构造函数,那么也就无法避免构造函数模式存在的问题 — 方法都在构造函数中定义,因此函数服用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。 考虑到这些问题,借用构造函数的技术也是很少单独使用的。

组合继承

组合继承:指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。
思路:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
好处:即通过在原型上定义方法实现了函数服用,又能够保证每个实例都有他自己的属性。

  1. function SuperType(name){
  2. this.name = name;
  3. this.colors = ['red','green']
  4. }
  5. SuperType.prototype.sayName = function(){
  6. console.log(this.name)
  7. }
  8. function SubType(name,age){
  9. SuperType.call(this,name);
  10. this.age = age;
  11. }
  12. SubType.prototype = new SuperType();
  13. SubType.prototype.getAge = function(){
  14. console.log(this.age)
  15. }
  16. let subtype = new SubType('lisi', 29)
  17. console.log(subtype)
  18. console.log(subtype.colors)
  19. subtype.sayName()
  20. subtype.getAge()

image.png