继承的几种方法

204 阅读3分钟

原型链继承

  • 原理:将子类的原型对象指向父类的实例
  • 优点: 1.继承了父类原型上的方法 2.继承了父类原型的属性
  • 缺点:1.无法像父类的构造函数传参 2.父类的引用对象会被所有子类的实例共享
    function Father(name,age) {
      this.name = name;
      this.age = age;
      this.test = 'zxx'
      this.arr=[1,2,3]
    }
    Father.prototype.say= function(){
      console.log(123);
    }
    function Son(name,age) {
      
    }
    //将子类的原型对象指向父类的实例
    Son.prototype = new Father()
    let son1 = new Son();
    let son2 = new Son();
    //父类的引用对象会被所有子类的实例共享
    //因为其实所有的实例都是引用的一个父类子类
    console.log(son1.arr === son2.arr);//true

构造函数继承

  • 原理:在子类的构造函数中,显式绑定this到子类实例并调用
  • 优点:1.实现了像父类构造函数传参 2.父类的引用对象被隔离开来了
  • 缺点:1.无法继承父类原型上的方法和属性 2.每个实例都会有父类构造函数的副本 3.每调用一次子类的构造函数也会调用一次父类的构造函数
    function Father(name,age) {
      this.name = name;
      this.age = age;
      this.test = 'zxx';
      this.arr = [1,2,3];
    }
    Father.prototype.say=function(){
      console.log(123);
    }
    function Son(name,age) {
    //每调用一次子类的构造函数也会调用一次父类的构造函数
    //在子类的构造函数中,隐式绑定this到子类实例构造函数并调用
      Father.call(this,name,age)
    }
    let son1 =new Son('test',20);//每个实例都会有父类构造函数的副本
    //son1.say()//报错,无法继承父类原型上的方法和属性

组合继承

  • 结合原型式继承和构造函数继承
  • 优点:几乎解决了上述的缺点
  • 缺点:1.调用了2次父类构造函数 2.子类的原型对象会有父类的实例属性
    function Father(name,age) {
      this.name = name;
      this.age = age;
      this.test = 'zxx';
      this.arr = [1,2,3];
    }
    //原型链继承
    //因为prototype被替换了,得加上constructor属性
    Son.prototype = new Father()
    Son.prototype.constructor = Son
    function Son(name,age) {
    //构造函数继承
      Father.call(this,name,age)
    }

原型式继承

  • 原理:在内部创造一个定义一个函数,并且把这个函数的原型对象执行传入的对象,最后返回一个新对象。
  • 优点:1.不用创建一个新的构造函数
  • 缺点:1.如果参数相同的话,实例会共享进行共享 2.不能对创造的新对象进行包装
    //原式继承
    function object(obj){
      function F(){};
      F.prototype = obj;
      return new F();
    }

寄生式继承

  • 原理:对新对象进行一次封装
  • 优点:1.扩展了新对象的属性和方法
    function Factory(obj){
      let car = object(obj)
      car.sayHi = function(){
        console.log('sayHi');
      }
      return car;
    }

组合式寄生式继承

  • 原理:1.用了寄生虫式继承+2.构造函数式继承
  • 寄生虫式继承解决了Son的修正了组合式继承原型链被改变的问题,这时原型上不在有父类构造函数的实例属性了
    function Father(){
      this.name = name;
      this.say = function(){
        console.log('say');
      }
    }
    Son.prototype = Object.create(Father.prototype);
    Son.prototype.constructor = Son;
    
    function Son(){
      Father.call(this)
    }

Object.create

  • 其实内部就是原型式继承
  • 注意当原型对象修改之后,要加上constructor属性
function Create(obj){
	function F(){};
    F.prototype = obj;
    F.prototype.constructor = F;
    return new F()
}