理解JavaScript继承(二)
5.寄生式继承
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function createAnother(original){
var clone = object(original);//通过调用函数创建一个新对象
clone.sayHi=function(){//以某种方式增强这个对象
alert("hi");
};
return clone;//返回这个对象
}
var person={
name:"Nicholas",
friends:["Shelby","Court,"Van"]
};
var anotherPerson=createAnother(person);
anotherPerson.sayHi();//"hi"
这个实例基于person返回了一个新对象anotherPerson。新对象不仅具有person的所有属性和方法,而且还有自己的sayHi()方法。
缺点:和构造函数一样,不能做到函数复用而降低效率。
6.寄生组合式继承
前面介绍说组合继承是JavaScript最常用的继承模式;实际上,它也存在一些问题,组合继承的最大问题是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。
组合式继承实例
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);//第二次调用SuperType()
this.age = age;
}
SubType.prototype = new SuperType();//第一次调用SuperType()
SubType.prototype.sayAge = function(){
alert(this.age);
};
在第一次调用SuperType()构造函数时,SubType.prototype会得到两个属性:name和colors;他们都是SuperType的实例属性,只不过现在位于SubType的原型中。当调用SubType构造函数时,又会调用一次SuperType构造函数,这一次又在新对象上创建了实例属性name和colors,于是,这两个属性就屏蔽了原型中的两个同名属性。
上面一共有两组name和colors属性:一组在实例上,一组在SubType原型中。这就是调用两次SuperType的结果。
为了解决这种情况,于是就出现了下面的——寄生组合式继承方法。
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。(之所以是超类型的副本,而不是直接是超类型,如果直接是超类型的话。当子类型为原型添加方法时,也会影响到超类型的)
寄生组合式继承
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.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, 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); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
上面实例只在SuperType.call(this, name);这调用了一次构造函数,并且因此避免了在prototype上面创建不必要的,多余的属性。
注:YUI的extend()就是采用这种寄生组合式继承