继承

30 阅读2分钟

继承

子类继承父类的属性和方法

  • 特点:
    • 子类拥有父类的属性和方法
    • 子类可以有自己新的属性和方法
    • 子类可以重写父类的方法

构造函数继承(冒充继承)

  • 父类只能把构造函数中的属性和方法继承给子类
  • 父类原型中的属性和方法无法继承给子类
    //父类
    function Father(name,age){
      this.name = name;
      this.age = age;
    }

    Father.prototype.run=function(){
      console.log("run...");
    }

    // 子类
    function Son(name,age,sex){
      //可以通过call,bind,apply
      Father.call(this,name,age);
      this.sex =sex;
    }

    var dad =new Father("dad",40);
    var son =new Son("son",11,"male")

     console.log(dad);//Father {name: 'dad', age: 40} 原型中有run方法
    console.log(son);//Son {name: 'son', age: 11, sex: 'male'} 没有继承父类原型的属性和方法

原型继承

  • 父类可以把原型上的属性和方法继承给子类
  • 子类无法设置初始值
//父类
  function Father(name,age){
    this.name = name;
    this.age = age;
  }

  Father.prototype.name = "dad";
  Father.prototype.age = 40;
  Father.prototype.run =function(){
    console.log("run...");
  }

  //子类
  function Son(){
  }

  Son.prototype = new Father();

  var dad = new Father("dad",40);
  var son = new Son("son",11)
  console.log(dad); //有初始值
  console.log(son); //无法设置初始值
  • 多个实例对引用类型的操作会被篡改

function DadType(){
  this.colors = ["red", "blue", "green"];
}
function SonType(){}

SonType.prototype = new DadType();

var instance1 = new SonType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"

var instance2 = new SonType(); 
alert(instance2.colors); //"red,blue,green,black"

组合继承(构造函数继承+原型继承)

  • 父类的属性用构造函数继承
  • 父类的方法用原型继承
//父类
    function Father(name,age){
        this.name =name;
        this.age =age;
    }

    Father.prototype.run = function(){
        console.log("run...");
    }

    //子类
    function Son(name,age,sex){
        Father.call(this,name,age)
        this.sex = sex;
    }

    Son.prototype = new Father();
    var  father = new Father("dad",40);
    var  son = new Son("son",11,"male");
    
    console.log(father);
    console.log(son);
  • 子类的原型(Father)的属性会是undefined

寄生组合继承

  • 解决了组合继承中的子类的原型(Father)的属性会是undefined问题
 function inheritProto(base,child){
    //通过Object.create(base.prototype)创造出一个新的对象
    //并且将base.prototype设置为新创建的对象的原型
    const baseProto = Object.create(base.prototype);

    baseProto.constructor = child;

    child.prototype = baseProto;
}

//父类
function Father(name,age){
    this.name = name;
    this.age = age;
}

Father.prototype.run = function(){
    console.log("run...");
}

//子类
function Son(name,age,sex){
    Father.call(this,name,age)
    this.sex = sex;
}

//原型继承
inheritProto(Father,Son);

var son = new Son("son",11,"male");
console.log(son);

ES6的class和extends继承

  • 通过constructor方法接收参数,并使用this关键字引用类的实例对象
  • 在创建实例对象时,构造函数会接受相应的参数并将它们分配给对象的属性
//父类
class Father{
    constructor(name,age){
        this.name =name;
        this.age =age;
    }
    run(){
        console.log("run...");
    }
}

//子类
class Son extends Father{
    constructor(name,age,sex){
        super(name,age)
        this.sex =sex;
    }
}

var dad = new Father("dad",40);
var son = new Son("son",11,"male");
console.log(dad);
console.log(son);