寄生组合继承称为完美继承(其他继承方式都有缺陷)
以下为6种继承的简单写法:
(包括:原形链、借用构造函数、组合继承、原形式、寄生式、寄生组合式6种继承)
//父类
function Parent(name) {
this.name = name;
}
Parent.prototype.alertHi = function () {
alert("Hi");
};
//原形链继承
function Child1() {}
Child1.prototype = new Parent();
//借用构造函数继承
function Child2(name) {
Parent.call(this,name);
}
//组合式继承
function Child3(name) {
Parent.call(this,name);
}
Child3.prototype = new Parent();
Child3.prototype.constructor = Child3;
//原形式继承
var Child4 = Object.create(Parent);
//寄生式继承
function createChild(child) {
var clone = Object(child);
clone.sayHello = function () {
alert("Hello");
};
return clone;
}
var Child5 = createChild(Person);
//寄生组合式继承
var Child6 = function (name) {
Parent.call(this,name);
};
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
inheritPrototype(Child6,Parent);
以下为6种继承的详细写法。
原形链继承
//原形链继承
//父类
function Parent() {
this.flag = true;
}
//父类的原形方法
Parent.prototype.alertFlag = function () {
alert(this.flag);
};
//子类
function Child() {
this.flag = false;//修改属性(不写则不修改)
}
//Child 继承 Parent
Child.prototype = new Parent();
//添加原形方法
Child.prototype.sayHello = function () {
alert("Hello");
};
var child = new Child();
child.alertFlag();//弹出 false
child.sayHello();// 弹出 Hello
//子类修改父类方法
Child.prototype.alertFlag = function () {
alert(!this.flag);
};
child.alertFlag();//弹出 true
//总结:继承的方法为 Child.prototype = new Parent();(只有一句话)
借用构造函数继承
//借用构造函数继承
function Parent(name) {
this.name = name;
}
function Child(name,age) {
Parent.call(this,name);
this.age = age;
}
//实例
var child = new Child("Andy",28);
alert(child.name);//Andy
alert(child.age);//28
//总结:继承的代码为Parent.call(this,name);(也是一句话),主要解决了this指向的转变和参数的传递。
组合继承
//组合继承
//父类
function Parent(name) {
this.name = name;
this.friends = ["Jay","Jolin"];
}
Parent.prototype.sayName = function () {
alert(this.name);
};
//子类
function Child(name,age) {
Parent.call(this,name);
this.age = age;
}
//继承
Child.prototype = new Parent();
//改变constructor指向
Child.prototype.constructor = Child;
//子类添加方法
Child.prototype.sayAge = function () {
alert(this.age);
};
//创建实例
var c1 = new Child("Andy",29);
var c2 = new Child("Lucy",24);
c1.friends.push("Jack");
c2.friends.push("Coco");
console.log(c1.friends.toString());//Jay,Jolin,Jack
console.log(c2.friends.toString());//Jay,Jolin,Coco
console.log(c1.sayName());//Andy
console.log(c2.sayName());//Lucy
原形式继承
//原形式继承
//实现继承的方法
function obj(o) {
function F() {}
F.prototype = o;
return new F();
}
//但是ECMA5,通过Object.create()方法规范化了原形式继承(即上面的方法)
var person = {
name:"Andy",
age:29,
friends:["Lily","Lucy","Jack"]
};
var Jay = Object.create(person);
Jay.name = "Jay";
Jay.friends.push("Jolin");
var Coco = Object.create(person);
Coco.name = "Coco";
Coco.friends.push("Sunny");
console.log(Jay.name);//Jay
console.log(Coco.name);//Coco
console.log(Jay.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
console.log(Coco.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
//没有重写的属性会被共享
var K = Object.create(person);
K.name = "Coco";
K.friends = ["J","Q","A"];
console.log(Jay.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
console.log(Coco.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
console.log(K.friends.toString());//J,Q,A
寄生式继承
//寄生式继承
//通过该方法,为子类添加方法,以实现继承;(即增强子类)
function create(child) {
var clone = Object(child);
clone.sayHi = function () {
alert("Hi");
};
return clone;
}
var Me = {
name : "Firefly",
friends:["Bee","Cicada","Butterfly"]
};
var me = create(Me);
me.sayHi();
寄生组合继承(又称完美继承)
//寄生组合继承
function Parent(a) {
this.a = a;
}
Parent.prototype = {
fn:function () {
alert("Hi");
}
};
function Child(a,b) {
Parent.call(this,a);
this.b = b;
}
//实现继承的方法
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
//继承
inheritPrototype(Child,Parent);
//为Child添加原型方法
Child.prototype.sayB = function () {
alert(this.b);
}
注:以下着重介绍组合寄生继承。
例:
function Super(name) {
this.name = name;
}
Super.prototype = {
constructor:Super,
sayName:function () {
alert(this.name);
}
//其他方法...
};
function Sub(name,age){
Super.call(this,name);
this.age = age;
}
//实现继承
inheritPrototype(Sub,Super);
//添加原形方法
Sub.prototype.sayAge = function () {
alert(this.age);
};
//实现继承的方法
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
//创建实例
var s = new Sub("Andy",28);
//调用方法
s.sayName();
s.sayAge();
//修改属性
s.age = 24;
s.sayAge();
s.name = "Lily";
s.sayName();
实现多继承(修改inheritPrototype()方法)
//父类1
function Super1(name) {
this.name = name;
}
Super1.prototype = {
constructor:Super1,
sayName:function () {
alert(this.name);
}
//其他方法...
};
//父类2
function Super2(gender) {
this.gender = gender;
}
Super2.prototype = {
constructor:Super1,
sayGender:function () {
alert(this.gender);
}
//其他方法...
};
//子类
function Sub(name,gender,age){
Super1.call(this,name);
Super2.call(this,gender);
this.age = age;
}
inheritPrototype(Sub,Super1);
inheritPrototype(Sub,Super2);
//添加原形方法
Sub.prototype.sayAge = function () {
alert(this.age);
};
//实现继承的方法
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
//修改的地方
//subType.prototype = prototype;
for(par in prototype){
subType.prototype[par] = prototype[par];
}
}
//创建实例
var s = new Sub("Andy","man",26);
s.sayName();
s.sayGender();
s.sayAge();
另外,你可以将Super1、Super2和Sub类放在不同的js文件中,在html中引入后调用。
例如:
//将以下代码方法myjs1.js文件中
function Super1(name) {
this.name = name;
}
Super1.prototype = {
constructor:Super1,
sayName:function () {
alert(this.name);
}
//其他方法...
};
//将以下代码放入myjs2.js文件中
function Super2(gender) {
this.gender = gender;
}
Super2.prototype = {
constructor:Super1,
sayGender:function () {
alert(this.gender);
}
//其他方法...
};
//将以下代码放入myjs3.js文件中
function Sub(name,gender,age){
Super1.call(this,name);
Super2.call(this,gender);
this.age = age;
}
inheritPrototype(Sub,Super1);
inheritPrototype(Sub,Super2);
//添加原形方法
Sub.prototype.sayAge = function () {
alert(this.age);
};
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
//subType.prototype = prototype;
for(par in prototype){
subType.prototype[par] = prototype[par];
}
}
//在html中引用
<script src="myjs1.js"></script>
<script src="myjs2.js"></script>
<script src="myjs3.js"></script>
<script>
//创建实例
var s = new Sub("Andy","man",26);
s.sayName();
s.sayGender();
s.sayAge();
</script>
Demo:超级玛丽
超级玛丽,有两个属性:name和size,有三个方法:show()、run()和jump();
大的超级玛丽:继承自超级玛丽,在超级玛丽的三个方法基础上修改一个方法:jump();
医生超级玛丽:继承自大的超级玛丽,在大的超级玛丽的三个方法基础上多了一个方法:shot();
超级玛丽类(js1.js):
function SuperMarie(name,size) {
this.name = name;
this.size = size;
}
SuperMarie.prototype = {
constructor:SuperMarie,
jump:function () {
console.log(this.name+" jump.");
},
run:function () {
console.log(this.name+" run.");
},
show:function () {
console.log(this.name+"'s size is "+this.size);
}
};
大的超级玛丽类(js2.js):
function BigSuperMarie(name,size) {
SuperMarie.call(this,name,size);
}
inheritPrototype(BigSuperMarie,SuperMarie);
BigSuperMarie.prototype.jump=function () {
console.log(this.name+" super jump!");
};
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
for(par in prototype){
subType.prototype[par] = prototype[par];
}
}
医生超级玛丽类(js3.js):
function DoctorSuperMarie(name,size) {
BigSuperMarie.call(this,name,size);
}
inheritPrototype(DoctorSuperMarie,BigSuperMarie);
DoctorSuperMarie.prototype.shot = function () {
console.log(this.name+" shot!");
};
function inheritPrototype(subType,superType) {
var prototype = Object(superType.prototype);
prototype.constructor = subType;
for(par in prototype){
subType.prototype[par] = prototype[par];
}
}
html代码:
<button id="SuperMarie">Super Marie</button>
<button id="BigSuperMarie">Big Super Marie</button>
<button id="DoctorSuperMarie">Doctor Super Marie</button>
<br>
<button id="sizeBtn">Size</button>
<button id="runBtn">Run</button>
<button id="jumpBtn">Jump</button>
<button id="shotBtn">Shot</button>
<script src="js1.js"></script>
<script src="js2.js"></script>
<script src="js3.js"></script>
<script>
var sm = new SuperMarie("Super Marie","small");//超级玛丽实例
var bigSm =new BigSuperMarie("BigSuperMarie","big");//大的超级玛丽实例
var docSm = new DoctorSuperMarie("DoctorSuperMarie","big");//医生超级玛丽实例
var smBtn = document.getElementById("SuperMarie");//按钮:超级玛丽变小
var bigSmBtn = document.getElementById("BigSuperMarie");//按钮:超级玛丽变大
var docSmBtn = document.getElementById("DoctorSuperMarie");//按钮:超级玛丽变成医生超级玛丽
var sizeBtn = document.getElementById("sizeBtn");//按钮:显示超级玛丽的大小
var jumpBtn = document.getElementById("jumpBtn");//按钮:超级玛丽跳跃
var runBtn = document.getElementById("runBtn");//按钮:超级玛丽奔跑
var shotBtn = document.getElementById("shotBtn");//按钮:超级玛丽射击
var me = "SuperMarie";
smBtn.addEventListener("click",function () {
me = "SuperMarie";
console.log("I am SuperMarie!");
});
bigSmBtn.addEventListener("click",function () {
me = "BigSuperMarie";
console.log("I am BigSuperMarie!");
});
docSmBtn.addEventListener("click",function () {
me = "DoctorSuperMarie";
console.log("I am DoctorSuperMarie!");
});
sizeBtn.addEventListener("click",function () {
if(me==="SuperMarie"){
sm.show();
}else if(me==="BigSuperMarie"){
bigSm.show();//方法继承自父类
}else if(me==="DoctorSuperMarie"){
docSm.show();//方法继承自父类
}
});
jumpBtn.addEventListener("click",function () {
if(me==="SuperMarie"){
sm.jump();
}else if(me==="BigSuperMarie"){
bigSm.jump();//修改父类方法
}else if(me==="DoctorSuperMarie"){
docSm.jump();//方法继承自父类
}
});
runBtn.addEventListener("click",function () {
if(me==="SuperMarie"){
sm.run();
}else if(me==="BigSuperMarie"){
bigSm.run();//方法继承自父类
}else if(me==="DoctorSuperMarie"){
docSm.run();//方法继承自父类
}
});
shotBtn.addEventListener("click",function () {
if(me==="SuperMarie"){
console.log("I can't shot!");
}else if(me==="BigSuperMarie"){
console.log("I can't shot!");
}else if(me==="DoctorSuperMarie"){
docSm.shot();
}
})
</script>