5种继承的理解

189 阅读2分钟

借用构造函数:在子类型构造函数的内部调用超类型构造函数.

function Father(){
    this.shoe = ["aj1*off","aj1*ts","aj4*kaws"];
}
function Son(){
    Father.call(this);              //继承了Father的全部,且向父类型传递参数
}
var instance1 = new Father();
instance1.shoe.pop("aj1*off");
console.log(instance1.shoe);      //["aj1*ts","aj4*kaws"]

var instance2 = new Son();
console.log(instance2.shoe);      //["aj1*off","aj1*ts","aj4*kaws"] 可见引用类型值是独立的

随之而来的是, 如果仅仅借用构造函数,那么将无法避免构造函数模式存在的问题–方法都在构造函数中定义, 因此函数复用也就不可用了.而且超类型(如Father)中定义的方法,对子类型而言也是不可见的. 考虑此,借用构造函数的技术也很少单独使用.

组合继承 :在借用构造函数继承中弥补了他的缺点:使用原型链实现对原型属性和方法的继承

function Father(name){
    this.name = name;
    this.shoe = ["aj1*off","aj1*ts","aj4*kaws"];
}
Father.prototype.sayName = function(){
    alert(this.name);
};
function Son(name,age){
    Father.call(this,name);         //继承实例属性,第一次调用Father()
    this.age = age;
}
Son.prototype = new Father();       //继承父类方法,第二次调用Father()
Son.prototype.sayAge = function(){
    alert(this.age);
}
var instance1 = new Son("Aimlessly",1);
instance1.shoe.push("aj6");
console.log(instance1.shoe);        //["aj1*off","aj1*ts","aj4*kaws""aj6"]
instance1.sayName();                //Aimlessly
instance1.sayAge();                 //2

这种继承的优点是可以对实例属性和原型属性和方法的继承,但是两次父类构造函数, 造成了不必要的消耗

原型继承:先创建一个临时性的构造函数, 然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例.

  • 在 ECMAScript5 中,通过新增 object.create() 方法规范
  • object.create() 接收两个参数:
    1. 一个用作新对象原型的对象
    2. (可选的)一个为新对象定义额外属性的对象
var shoeBox = {
    shoe : ["aj1*off","aj1*ts","aj4*kaws"]
};
var anotherShoeBox = Object.create(shoeBox);
anotherShoeBox.shoe.push("yeezy350");
alert(person.shoes);                  //["aj1*off","aj1*ts","aj4*kaws","yeezy350"]

不能够复用,而且由于ES5中提出所以有兼容问题

寄生式继承:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象(类似工程模和构造函数)

function createAnother(original){
    var clone = object(original);           //通过调用object函数创建一个新对象
    clone.sayHi = function(){               //以某种方式来增强这个对象
        alert("hi");
    };
    return clone;                           //返回这个对象
}

不能够复用

寄生组合式继承:和名字一样是寄生组合时继承的融合

function extend(subClass, superClass) {
  var F = function() {};
  F.prototype = superClass.prototype;
  subClass.prototype = new F(); 
  subClass.prototype.constructor = subClass;

  subClass.superclass = superClass.prototype;
  if(superClass.prototype.constructor == Object.prototype.constructor) {
    superClass.prototype.constructor = superClass;
  }
}