理解JavaScript继承(二)

时间:2022-04-07 07:35:52

理解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()就是采用这种寄生组合式继承