通过单独使用原型链继承,虽然功能非常强大,但是存在各方面的问题。例如:子类的实例需要单独的超类属性时,需要传递参数时....这时候,需要用到构造函数。
而只使用构造函数进行继承时,通过构造函数创建的方法无法共享,每个子类实例都会拥有一个方法对象,实非明智之举。如此,只有结合二者之长,才是比较完美的继承模式,当然,如何结合使用,还得看实际的使用环境。
下面用个经典的例子来说明:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-Transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="author" content="Cycle" />
<title>Classical inheritance pattern</title>
<script type="text/javascript">
/*组合继承,也叫伪经典继承,发挥构造函数和原型链二者之长*/
function SuperType(name, age){
this.name = name;
this.age = age;
this.colors = ["black", "white", "blue"]; //引用类型
}
SuperType.prototype.getBaseInfo = function(){
return "Name: " + this.name + " Age: " + this.age;
};
function SubType(name, age, job, pay){
SuperType.call(this, name, age); //借用构造函数,让实例都拥有属性的副本
this.job = job;
this.pay = pay;
}
SubType.prototype = new SuperType(); //原型链继承,让实例共享方法,省去不必要的对象内存
SubType.prototype.getJobInfo = function(){
return "Job: " + this.job + " Pay: " + this.pay;
};
var p1 = new SubType("Cycle", "27", "Software Engineer", "7500");
alert(p1.getJobInfo());
alert(p1.getBaseInfo());
alert(p1.name);
alert(p1.job);
p1.colors.push("red", "yellow");
alert(p1.colors);
var p2 = new SubType("Picker", "29", "Software Engineer", "8000");
alert(p2.getJobInfo());
alert(p2.getBaseInfo());
alert(p2.name);
alert(p2.job);
alert(p2.colors);
</script>
</head>
<body>
<p><a href="#">listen to your heart</a></p>
<p><a href="#">she will be love - Maroon</a></p>
<p><a href="#">all for you - Ace Of Base</a></p>
<p><a href="#">lucky star - Joana Zimmer</a></p>
</body>
</html>
上面案例,使用到function.call()方法进行继承,让每个子类实例都可以拥有属性的副本,实现实例间的属性无干扰(也可以使用apply()方法,参数传递数组)。另外,子类SubType的原型对象prototype指向超类的新实例,如此继承,既可以实现函数方法的复用,又可以让每个实例都拥有自己的属性。
此方式也存在一定缺陷:两次调用超类的构造函数。可以考虑使用Parasitic combined inheritance(寄生组合式继承)。
注:body元素中的内容无关主题。
Parasitic combined inheritance(寄生组合式继承)案例说明:
// function object(original){
// function Temp(){}
// Temp.prototype = original;
// return new Temp();
// }
function inheritPrototyep(subType, superType){ //寄生组合式继承
var prototype = Object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name){
this.name = name;
this.colors = ["red", "black", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototyep(SubType,SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
};
var p1 = new SubType("Tom", 30);
var p2 = new SubType("Jack", 32);
p1.colors.push("white");
alert(p1.colors);
alert(p2.colors);
p1.sayName();
p2.sayName();