你不知道的继承

1,原型链继承

  父: SuperType

  子: SubType

  SubType.prototype = new SuperType();  // 继承了SuperType

  实现的本质是重写原型对象;即重写了子类的原型 prototype ,创建SuperType实例,并将该实例赋值给SubType.prototyp实现的。

  不足: 

    • 主要是来自引用类型值的原型,即引用类型值的原型属性会被所有实例共享。
    • 在创建子类型的实例时,不能向超类型的构造函数传递参数。

2,借用构造函数(伪造对象或经典继承)

   原理: 在子类构造函数内部调用超类型的构造函数。即函数只不过是在特定环境中执行代码的对象,因此通过使用call() 和 apply() 方法可以在

     新创建的对象上执行构造函数。

  function SubType (name) { 
      // 继承了 SuperType
      SuperType.call (this,name);  
  }

child = new SubTyp('hello');

  优点: 可以利用call 方法,进行传递参数。

      不足: 如果仅利用构造函数,那么函数复用就无从谈起了,而且超类型中定义的方法,对子类型而言是不可见的。

3,组合式继承(伪经典继承)

  原理:指的是将原型链和借用构造函数的技术组合在一起,从而发挥二者之长的一种继承模式。其背后的思路就是

     使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,

     既通过在原型上定义方法实现了函数复用,又能保证每个实例都有自己的属性。

  

    function SuperType(name) {
      this.name = name;
    }
    function SubType () { 
      // 继承了 SuperType
      SuperType.call (this);  
    }

    SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;

   优点: 组合继承避免了原型链和借用构造函数的缺陷,融合了两者的优点,成为JavaScript中常用的继承模式,

       而且,instanceOf 和 isPrototypeOf ()  也能够用于识别基于组合继承创建的对象。

   不足: 无论什么情况下,都会调用二次超类型构造函数。

4, 原型式继承

  原理:借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

      

    function object(o) {
      function F() {};
      F.prototype = o;
      return new F();
    }

  其中,es5通过新增 Object.create()方法规范化了原型式继承。这个方法接受两个参数:一个用作新对象原型的对象和一个新对象定义额外属性的对象(可选的)。

  在传入一个参数的情况下,Object.create() 与 object() 方法的行为相同。

5,寄生式继承

  原理:与原型式继承紧密相关的一种思路,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再将该对象返回。

  

    function createAnother() {
      let clone = object(original);
      clone.sayHi = function() {
        alert('hi');
      }
      return clone;
    }

  使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率,这一点与构造函数模式类似。

6,寄生组合式继承

    原理: 通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。即 不必为了指定子类型的的原型而调用超类型的构造函数,我们需要的无非就是超类型原型的一个副本而已。

    

    function inheritPrototype(subType, superType) {
      // 创建父类一个副本
      let prototype = object.create(superType.prototype);
      // 弥补重新原型失去的constructor属性
      prototype.constructor = subType;
      // 将副本 赋值给子类的原型
      subType.prototype = prototype;
    }
原文地址:https://www.cnblogs.com/strivegys/p/14052536.html