原型链/原型继承

98 阅读2分钟

主要有基类SuperType, 需要子类SubType继承基类SuperType


   function SuperType(name) {
      this.name = name;
      this.colors = ['red']
   }

   SuperType.prototype.getName = function() {
      return this.name
   }

   function SubType(age) {
     this.age = age; 
   }

方法一: 原型链

原型链的实现方式如下

    SubType.prototype = new SuperType('test')
   /*
      如果通过对象添加新方法,原型对象会被替换,导致原型链断裂
    SubType.prototype = {
        getName() {return this.name},
        otherMethod() {console.log('other')}
    }
   **/

但是,当它里面包含引用值的时候,通过某个实例修改值会导致所有值都变化;同时,子类型在实例化的时候没法给基类构造函数传参数

    var instance1 = new SubType();
    instance1.colors.push('green');
    console.log(instance1.colors) // red, green

     var instance2 = new SubType();
    console.log(instance2.colors) // red, green

方法二:盗用构造函数(call, apply)

盗用构造函数的实现方式如何

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

上面关于子类引用值的问题就得以解决了, 但是它也有缺点,它的缺点是必须在构造函数中定义方法,且函数不能重用。子类不能访问基类原型上的方法

  var instance1 = new SubType();
    instance1.colors.push('green');
    console.log(instance1.colors) // red, green

     var instance2 = new SubType();
    console.log(instance2.colors) // red

    instance1.getName() // Uncaught TypeError:instance1.getName is not a function

image.png

方法三: 组合继承

组合继承 = 原型链(主要继承方法) + 组合继承(主要继承属性,constructor里的内容),这种方法是js中用的最多的方法,其实现方式如下

    function SubType(name, age) {
        // 继承属性
        SuperType.call(this, name); // 第二次调用SuperType()
        this.age = age;
    }
    
   // 继承方法
   SubType.prototype = new SuperType(); // 第一次调用SuperType()

它的方法缺点是SuperType()方法会被执行2次

方法四: 原型式继承

它主要是实现Object.create的功能,实现方式如下,它也存在引用值数据共享的问题。
    function object(original) {
       var F = function(){};
       F.prototype = original;
       return new F();
    }

方法五: 寄生式继承

它和方法四比较接近,它的思路采用寄生构造函数+工厂模式,其实现方法如下所示

    function createObject(original) {
        var clone = object(original) // 创建新对象
        clone.method = function() {console.log('new method')} // 对original对象的增强
        return clone;
    }

寄生式继承主要关注对象,不在乎类型和构造函数的场景

方法六: 寄生组合式继承

它的主要思路是通过寄生式继承来继承基类原型,然后返回新对象赋值给子类原型。其实现方法如下所示

    function inheritProperType(SubType, SuperType) {
        var prototype = object(SuperType.prototype) // 继承基类原型
        prototype.constructor = SubType;
        SubType.prototype = prototype;
    }

总结: 关于原型链(方法1-3)/原型(方法4-6)的继承,主要是通过 new SuperType(),SuperType.call(this,...arguments),object复制SuperType.prototype的方式以及上面几种的组合来实现的