js原型继承的几种方法

1. 原型链继承

利用原型链来实现继承,父类的一个实例作为子类的原型

function child(){
  this.xx = 'xx'; //子类自己的定义
}
child.prototype = new parent();
//这里new parent()父类对象并没有constructor属性,需要后面加上
child.prototype.constructor = child

原理: 子类的原型对象指向 父类的实例, 当子类实例找不到属性和方法时,会沿着原型链往上找。
优点:简单,既是子类实例也是父类实例,父类新加原型方法或者属性,子类都能访问到
缺点:

  1. 不能实现多继承,所有子类的实例的原型都共享一个父类实例属性和方法
  2. 不能传参

2. 构造函数继承

通过使用call、apply方法可以在新创建的对象上执行构造函数,用父类的构造函数来增加子类的实例

原理: 子类的构造函数中执行父类的构造函数,并且改变子类的this绑定

     // 创建子类、添加子类属性。
    function arrange(name){
      Person.call(this,name) // 执行父构造,将This指向本身,拉取父私有属性;
    }

优点:简单,直接父类的属性和方法
缺点:无法继承原型链上的属性方法

3. 寄生组合式继承

将父类原型对象直接赋值给子类的构造函数,再将空属性的构造函数实例赋值给子类原型对象

function Parent(name){
  this.name = name
}
Parent.prototype.getName = function(){
  return this.name
}
// 创建子类、添加子类属性。
function Child(name){
  Parent.call(this, name)// 执行父构造,将This指向本身,拉取父私有属性;
}

 // 子类的原型对象指向父类的原型对象
Child.prototype = Parent.prototype
 // 将constructor指向本身,保证原型链不断。
Child.prototype.constructor = Child

优点:完美实现继承,解决了组合式继承带两份属性的问题; new Child的时候不用 每次都 new Parent
缺点: 子类的prototype添加方法会影响 父类的prototype;

4. 寄生组合式继承(改进)

将父类原型对象直接赋值给子类的构造函数,再将空属性的构造函数实例赋值给子类原型对象

function Parent(name){
  this.name = name
}
Parent.prototype.getName = function(){
  return this.name
}
// 创建子类、添加子类属性。
function Child(name){
  Parent.call(this, name)// 执行父构造,将This指向本身,拉取父私有属性;
}

 // 子类的原型对象指向父类的原型对象
// 浅拷贝 解决问题
Child.prototype = Object.create(Parent.prototype)
 // 将constructor指向本身,保证原型链不断。
Child.prototype.constructor = Child

优点:完美实现继承,解决了组合式继承带两份属性的问题; new Child的时候不用 每次都 new Parent

5. 克隆原型链继承

将等待继承的原型对象克隆,再赋值给继承的原型对象

    // 创建子类、添加子类属性。
    function arrange(name){
      this.name = name;
      this.goShop = function(food){
        console.log(name + '叫你去买'+ food)
      }
    }
    // 创建克隆类型
    function Clone(obj){
      for(var key in obj){
        this[key] = typeof obj[key] == 'object' ? new Clone(obj[key]) : obj[key];
      }
    }
    // 使用Clone构造函数继承原型
    arrange.prototype = new Clone(Person.prototype); 
    // 将constructor指向本身,保证原型链不断。
    arrange.prototype.constructor = arrange; 

    //创建arrange新实例,也是Clone实例,却不在是Person实例;
    var newObj = new arrange('李四'); 
    console.log(newObj instanceof Person)  //false
    console.log(newObj instanceof arrange) //true
    console.log(newObj instanceof Clone) //true
    // 克隆成功,可以访问克隆对象的原型对象;
    console.log(newObj)
    console.log(newObj.name) // 李四
    newObj.eat('苹果'); // 李四正在吃:苹果
    newObj.goShop('香蕉'); // 李四叫你去买香蕉

优点:直接通过对象生成一个继承该对象的对象
缺点:不是类式继承,而是原型式基础,缺少了类的概念

参考: https://www.jb51.cc/note/413574.html
https://blog.csdn.net/qq_42926373/article/details/83149347

你可能感兴趣的:(js原型继承的几种方法)