JS各种继承原理详解以及优缺点

前置阅读:理解原型、new、构造函数

构造函数直接实现


function SuperType(){
    this.property =true;
}

function SubType(){
      SuperType.call(this);
}

//修改父类上的原型内容
SuperType.prototype.getType = function(){
    return 'add';
}
var instance = new SubType();

console.log(instance.property);
//true
console.log(instance.getType());
//报错:Uncaught TypeError: instance.getType is not a function
  • 问题:通过构造方法继承的子类,可以获取到父类构造函数当中的所有属性。

    • 子类就无法获取到父类prototype上变化的属性和方法。
    • 不好进行函数复用

原型继承


function SuperType(){
    this.property =true;
    this.colors = ['red','green'];
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
}

var parent = new SuperType();
function SubType(){
    this.property = false;//子类重写父类属性
}
//把子类的原型设置为父类的一个新的实例对象
//父类的实例的__proto__中指向它自己的原型对象
//所以这样子类也可以成功访问到
SubType.prototype = new SuperType(); 
SubType.prototype.getSubType = function(){
    return this.property;
}
var instance = new SubType();
console.log(instance.getSuperValue());//false
instance.colors.push('blue');
console.log(parent.colors);//'red','green',
var instance2 = new SubType();
console.log(instance2.colors);//'red','green','blue'
  • 问题:

    • 不同子类实例会共享同一个引用类型数据,所以如果有一个修改了它,其他实例访问到的也是修改之后的。
    • 创建子类实例的时候不能向构造参数传递参数。

原型继承.PNG

 组合继承:构造函数+原型继承

function SuperType(){
    this.property =true;
    this.colors = ['red','green'];
}
SuperType.prototype.getSuperValue = function(){
    return this.property;
}

var parent = new SuperType();
function SubType(arg){
    SuperType.call(this,arg);
    this.property = false;//子类重写父类属性
}

SubType.prototype = new SuperType(); 

SubType.prototype.getSubType = function(){
    return this.property;
}
var instance = new SubType();
console.log(instance.getSuperValue());//false
instance.colors.push('blue');
console.log(instance.colors);//'red','green','blue'
console.log(parent.colors);//'red','green',
var instance2 = new SubType();
console.log(instance2.colors);//'red','green'
  • 组合继承,具有了两种集成方式的有点,同时因为借用了父类的构造函数,所以每个子类实例获得了父类的属性。

    • 不足之处:每次都会调用两次超类的构造函数。一次是创建子类原型的时候,另一次是在子类构造函数内部。

组合继承.PNG

寄生继承:

  • 调用函数创建对象+增强该对象的属性和方法
 function createAnother(original){
  var clone = object(original);
  clone.sayHi = function(){
    console.log('hi');
  }
  return clone;
}

var person = {
  name:"sherry",
  friends:['lisa']
}
var p = createAnother(person);

最佳实践:寄生组合继承


function inheritPrototype(subType,superType){
  var prototype = object(superType.prototype);  
  prototype.contructor = subType;
  subType.prototype = prototype;
}

另一种实现方式:

 function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;
  }
  • 只调用一次superType的构造函数
  • 原型链也没有改变

参考:《Javascript高级教程》

阅读 124

推荐阅读