javascript学习笔记——原型链继承、经典继承、组合继承、寄生组合式继承

ECMAScript中函数没有没签名,所以无法实现接口继承(只继承方法签名),只支持实现继承(继承实际的方法),实现继承主要依靠原型链

1.原型链

①基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法;

继承是通过创建一个父类的实例,并将该实例赋值给子类的内部属性[[prototype]]实现的。原来存在于父类实例中的所有属性和方法,也存在于子类的prototype属性中。P163页(例子)

②默认的原型:所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向object.prototype,所以所有的引用类型都默认继承了Object;

③确定原型和实例的关系的方法

1)instanceof操作符:测试实例与原型链中出现过的构造函数

alert(p1 instanceof Object);   //true
alert(p1 instanceof Person);    //true

2)isPrototypeOf(),测试原型链中出现过的原型;

alert(Object.prototype.isPrototypeOf(p1));    //true

④子类型如果需要重写超类型中的某个方法或添加新方法,则必须在用超类型的实例替换原型之后,才能重写或添加方法;

子类型重写某方法后,通过子类实例调用该方法时,调用的是重写后的方法,而父类型的实例调用该方法,则还是重写前的方法;

⑤通过原型链实现继承时,不能使用对象字面量创建原型方法,防止原型链被重写,父类型和子类型之间的联系被切断;

⑥原型链的问题

问题一:在通过原型实现继承时,原型实际上变成另一个类型的实例,原型的实例属性变成现在子类型的原型属性,从而子类型的所有实例可以共享父类型中的所有属性和方法;

function superType(){

 this.color=["red","green","blue"];
  }
function SubType(){}

//继承SuperType
SubType.prototype=new SuperType();

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

var instance2=new SubType();
alert(instance21.color);        //"red,green,blue,black"

问题而:在创建子类型的实例时,不能像超类型的构造函数传递参数

所以在实践中很少但是使用原型链实现继承。

2.借用构造函数

借用构造函数也叫伪造对象或经典继承,解决引用类型值所带来的问题。

①基本思想:通过call()或apply()方法在子类型的构造函数中调用超类型的构造函数;

②可以在子类型的构造函数中向超类型构造函数传递函数;

function SuperType(name){
 this.name=name;
}

function SubType(){
  //继承了SuperType,同时还传递了参数
   SuperType.call(this,"amy");
  //实例属性
  this.age=23;
}

var instance=new SubType();
alert(instance.name);   //amy
alert(instance.age);     //23

③借用构造函数的问题

与构造函数模式一样,方法都在构造函数中定义,因此函数的复用就无从谈起了,所以很少单独使用;

3.组合继承

组合继承又叫伪经典继承,是js中最常用的继承模式。

①基本思想:使用原型链实现随原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承

②优点:既通过在原型上定义方法实现了函数的复用,又能保证每个实例都有它自己的属性。

③缺点:无论什么情况下,都会调用两次超类型构造函数,一次是在创建子类型原型的时候,另一次是在子类型构造函数内部;

function SuperType(name){
   this.name=name;
   this.color=["red","green"];
}

SuperType.prototype.sayName=function(){
  alert(this.name);
};

function SubType(name,age){
  //继承属性
  SuperType.call(this,name);     //第二次调用SuperType()
  this.age=age;
}
 
//继承方法
SubType.prototype=new SuperType();        //第一次调用SuperType()
SubType.prototype.constructor=SubType;
SubType.prototype.sayAge=function(){
  alert(this.age);
}

var instance1=new SubType("amy",23);
instance1.color.push("blue");   
alert(instance1.color);    //"red,green,blue"
instance1.sayName();     //amy
instance1.sayAge();     //23

var instance2=new SubType("grey",27); 
alert(instance2.color);    //"red,green"
instance2.sayName();     //grey
instance2.sayAge();     //27

   

javascript学习笔记——原型链继承、经典继承、组合继承、寄生组合式继承_第1张图片

有图可知,有两组name和color属性,一组在实例中,一组在SubType原型中,这就是两次调用SuperType构造函数的结果;

不同的实例既分别拥有自己的属性,又可以使用相同的方法

4.原型式继承

①基本思想:借助原型可以基于已有的对象创造新对象,同时还不必因此创建自定义类型;

②ES5使用Object.create()方法规范化了原型式继承

var person={
 name:"amy",
friend:["coco","rudy"]
};
var anoperson=Object.create(person);
anoperson.firend.push("rob");

var yetperson=Object.create(person,{name:{value:"lala"}});
yetperson.firend.push(linda);

alert(person.friend);       //"coco,rudy,rob,linda"
alert(yetperson.name);      //"lala"

在没有必要兴师动众的创建构造函数的,只想让一个对象与另一个对象保持类似的情况下,原型继承时完全可以胜任的,但是该继承方式还是跟原型模式一样,包含引用类型值的属性始终都会共享相应的值;

5.寄生式继承

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

②适用于此在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式的继承也是一种有用的模式。任何能够返回新对象的函数都适用于此模式。

③使用寄生式继承来为对象添加方法,会由于不能做到函数复用而降低效率;

6.寄生组合式继承

①含义:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

②基本思想:不必为了指定类型的原型而调用超类型的的构造函数,我们所需的无非就是超类型原型的一个副本而已,本质上,就是使用寄生式继承来继承超类型的原型,然后将结果指定给子类型的原型;

③其高效率体现在它只调用了一次父类型构造函数,并且避免了在子类型的原型中创建不必要的、多余的属性。而原型链还能保持不变,开发人员普遍认为这是引用类型最理想的继承方式

function object(o){
  function F(){}
  F.prototype=o;
  return new F();

}

function inheritPrototype(subtype,supertype){

     var prototype =object(supertype.prototype);   //创建对象
     prototype.constructor=subtype;                //增强对象
     subtype.prototype=prototype;                  //指定对象
}

function SuperType(name){
   this.name=name;
   this.color=["red","green"];
}

SuperType.prototype.sayName=function(){
  alert(this.name);
};

function SubType(name,age){
  //继承属性
  SuperType.call(this,name);     //调用SuperType()
  this.age=age;
}
 inheritPrototype(SubType,SuperType);

 SubType.prototype.sayAge=function(){
  alert(this.age);
}


var instance1=new SubType("amy",23);
instance1.color.push("blue");   
alert(instance1.color);    //"red,green,blue"
instance1.sayName();     //amy
instance1.sayAge();     //23

var instance2=new SubType("grey",27); 
alert(instance2.color);    //"red,green"
instance2.sayName();     //grey
instance2.sayAge();     //27

 

你可能感兴趣的:(javascript学习笔记)