js中的几种继承实现

173 阅读4分钟

原型继承(类式继承)

原型继承是怎么样继承的

// 声明父类
function Parent(){
    this.parentMoney = 100;
    this.getParentMoney = function(){
        console.log(this.parentMoney);
    }
}
// 给父类原型上添加公告的方法
Parent.prototype.getParentMoney = function(){
    console.log(this.parentMoney);
}
Parent.prototype.getParentName = function(){
    console.log(this.parentName);
}
// 声明子类
function Child(){
    this.childMoney = 10;
}
// 给子类原型上添加方法
Child.prototype.getChildMoney = function(){
    console.log('getChildMoney'+this.childMoney);
}
Child.prototype.getChildName = function(){
    console.log('getChildName'+this.childName);
}
// 继承父类
Child.prototype = new Parent();
Child.prototype.getChildMoneyNew = function(){
    console.log('getChildMoneyNew'+this.childMoney);
};
let child = new Child();

原型继承的思想

子类的原型指向父类的实例 Child.peototype = new Parent();

原型继承的特点

  • 1.并不会把父类中的方法克隆一份给子类,而是建立了子类与父类的原型链查找机制.
  • 2.因为重定向父类的原型后(Child.prototype = new Parent()),子类就丢失了原本的contructor属性或者是原来原型上该有的方法和属性(如getChildName和getChildMoney这两个方法就丢失掉了).
  • 3.子类或者子类的实例可以"肆意"的修改父类上的方法和属性,对父类可能造成一系列的破坏.(如child.__ proto__.getParentMoney=null);
  • 4.会把父类中私有的方法和属性作为子类的公有属性和方法继承过来.(父类中不管是私有还是公有都变成了子类的公有)

call继承

call继承是如何继承的

// 声明父类
function Parent(){
    this.parentMoney = 100;
    this.getParentMoney = function(){
        console.log(this.parentMoney);
    }
}
// 给父类原型上添加公告的方法
Parent.prototype.getParentMoney = function(){
    console.log(this.parentMoney);
}
Parent.prototype.getParentName = function(){
    console.log(this.parentName);
}
// 声明子类
function Child(){
    // call继承,是把父类作为函数执行,把this指向改完子类的this
    parent.call(this); // 相当于把父类中私有的方法和属性拿过来了
    /*
        this.parentMoney = 100;
        this.getParentMoney = function(){};
    */
    this.childMoney = 10;
}
// 给子类原型上添加方法
Child.prototype.getChildMoney = function(){
    console.log('getChildMoney'+this.childMoney);
}
Child.prototype.getChildName = function(){
    console.log('getChildName'+this.childName);
}
let child = new Child();

call继承的思想

把父类作为普通函数执行,让父类在子类中执行,方法中的this改变成子类的实例即可.

function Child(){
    Parent.call(this);
}

call继承的特点

  • 1.只能继承父类的私有属性(继承父类的私有属性赋值给子类的实例的私有属性),类似于拷贝,不是查找指向.
  • 2.只是把父类当做普通函数执行,所以无法继承父类原型上的方法.

寄生组合继承

寄生组合继承是如何继承的(call继承+变异版的原型继承)

// 声明父类
function Parent(){
    this.parentMoney = 100;
    this.getParentMoney = function(){ 
        console.log(this.parentMoney) 
    }
}
Parent.prototype.getParentMoney = function(){
    console.log(this.parentMoney) 
}
function Child(){
    parent.call(this);      // call继承,把父类中的私有变量继承过来
    this.childMoney = 10;
    this.getChildntMoney = function(){ 
        console.log(this.childMoney) 
    }
}
Child.prototype.getChildMoney = function(){
    console.log(this.parentMoney) 
}

function inheritPrototyepe(Parent,Child){
    /*
        参数: Parent: 父类
              Child: 子类
    */
    var obj = Object.prototype(Parent.peototype);
    Child.prototype = obj
    Child.prototype.constructor = Child;
}

寄生组合继承的思想

  • call继承: 私有继承
  • 变异版继承: 公有继承

寄生组合继承的特点

  • 1.call继承与变异版的原型继承,实现了私有到私有,公有到公有的继承
  • 2.由于还是要修改子类的原型,所以子类原型原本上的方法还是会丢失.

class继承

class继承是如何继承的?

class Parent{
    constructor(){
        // 给父类私有添加属性
        this.parentMoney = 100;
    }
    // 给父类原型上添加方法
    this.getParentMoney = function(){ 
        console.log(this.parentMoney) 
    }
    
    // 加上static,相当于把类当做普通对象设置的属性和方法
    static num = 100;
    static getNum(){
        cosole.log('哈哈哈')
    }
}
class Child extends Parent{
    constructor(){
        super();  // // 一旦使用了extends实现继承,只要子类写了constructor,就必须写super;
        // 给父类私有添加属性
        this.childMoney = 100;
    }
    // 给子类原型上添加方法
    this.getChildMoney = function(){ 
        console.log(this.childMoney) 
    }
}

class继承的特点

class继承相当于寄生组合继承

  • 1.extends关键字相当于寄生组合继承中的变异版原型继续
Child.prototype = Object.prototype(Parent.prototype);
Child.prototype.constructor = Child;
  • 2.super关键字相当于寄生组合继承中的call继承
function Child(){
    Parent.call(this);
}

类的多态: 重载与重写

在后台语言中(java)的重载和重写

  • 重载就是,函数名相同,传参不同或者返回值不同,就相当于一个函数的重载了
public String fn(a:number,b:number){
    return 'a+b';
}
public String fn(a:string,b:number){
    return a+b;
}
  • 重写: 就是子类重写父类的方法

在javscript中

  • 重载就是,函数根据传入的参数不同去做不同的事情.
function fn(a){
    if(typeof a === 'string'){
        console.log('string')
    }else if(typeof a === 'number'){
        console.log('number')
    }else{
        console.log('object')
    }
}
  • 重写: 就是把原来的方法覆盖掉.