许多OO语言都支持2种继承方式:接口继承和实现继承。
接口继承只继承方法签名,而实现继承则继承实际的方法。由于函数没有方法签名,在ECMAScript中无法实现接口继承。ECMAScript只支持实现继承,而实现继承主要是依靠原型链来实现的。
原型链
利用原型链让一个引用类型继承另一个引用类型的属性和方法。每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = false;
}
SubType.prototype = new SuperType();//继承了SuperType
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
SubType.prototype.getSuperValue = function(){
return false;
}
var instance = new SubType();
alert(instance.getSuperValue());
借用构造函数
function SuperTyper(){
this.colors = ["red","blue","green"];
}
function SubType(){
SuperType.call(this);//继承了SuperType
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);
var instance2 = new SubType();
alert(instance2.colors);
组合继承
伪经典继承,将原型链和借用构造函数组合到一起。使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
function SuperType(name){
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
}
function SubType(name,age){
SuperType.call(this, name);//继承属性
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
alert(instance1.colors);//"red,blue,green,black"
instance1.sayName();//"Nicholas"
instance1.sayAge();//29
var instance2 = new SubType("Greg",27);
alert(instance2.colors);
instance2.sayName();//"Greg"
instance2.sayAge();//27
原型式继承
ECMAScript5新增Object.create()方法规范化了原型式继承。
var person = {
name:"Nicholas",
friends:["Shelby","Court","Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name= "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);
var anotherPerson = Object.create(person, {
name:{
value: "Greg"
}
});
寄生式继承
与原型式继承紧密相关的一种思路。
创建一个仅用于封装继承过程的函数,改函数在内部以某种方式来增强对象,最后再像真的是它做所有工作一样返回对象。
function createAnother(original){
var clone = object(original);
clone.sayHi = function(){
alert("hi");
};
return clone;
}
寄生组合式继承
组合继承最大的问题就是无论什么情况下,都会调用2次超类型构造函数;一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
不必为了指定子类型的原型而调用超类型的构造函数,所需要的无非是超类型原型的一个副本而已。
function inheritPrototype(subType,superType){
var prototype = object(superType.prototype);//创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
使用最多的是组合继承,使用原型链继承共享的属性和方法,借用构造函数继承实例属性。