//js各種繼承的分析;
function Parent(name,age){
this.name=name;
? ? ? this.age=age;
? ? ? this.money=100;
? ? ? this.fly=function(){
console.log('這是對(duì)象本身的fly方法');
? ? ? }
}
Parent.prototype.sex='male';
Parent.prototype.play=function(){
console.log('這是原型上面的play方法');
}
var parent=new Parent('父親',45);
//1:第一種:原型指向父類實(shí)例
?function Sub(name,age) {
? ? ?this.name=name;
? ? ?this.age=age;
?}
?Sub.prototype=new Parent('天劫','18');
var? sub=new Sub('小明',11);
?var? sub1=new Sub('小紅',12);
?console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);true;
//? 優(yōu)點(diǎn):
?這是一個(gè)非常純粹的繼承,實(shí)例是子類的實(shí)例沫勿,也屬于父級(jí)的實(shí)例,父類的屬性方法以及父類原型上添加的屬性或方法哺壶,子類都可以訪問(wèn)得到啸澡;
?缺點(diǎn):
?原型對(duì)象上的引用屬性吝镣,所有的實(shí)例都是共享的钝诚,即在一個(gè)實(shí)例上修改,所有的實(shí)例均跟著變化蝗蛙;
?不能同時(shí)繼承多個(gè)父類蝇庭。
第二種:構(gòu)造函數(shù)
?function Sub(name,age) {
? ? ?Parent.apply(this);
? ? ?this.name=name;
? ? ?this.age=age;
?}
?var? sub=new Sub('小明',11);
?var? sub1=new Sub('小紅',12);
?console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);false;
// 優(yōu)點(diǎn):
?這種繼承方式解決了傳統(tǒng)繼承中共享引用屬性的問(wèn)題;
?創(chuàng)建子類實(shí)例的時(shí)候可以向父級(jí)傳遞參數(shù)捡硅;
?可以繼承多個(gè)父類;
// 缺點(diǎn):
/只能繼承父類構(gòu)造函數(shù)里面的屬性方法盗棵,不會(huì)繼承父類原型上的屬性方法壮韭;
無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類都有父類實(shí)例的副本纹因,影響性能喷屋;
?實(shí)例只是子類的實(shí)例不是父類的實(shí)例。
第三種:原型指向父類實(shí)例+構(gòu)造函數(shù)
?function Sub(name,age) {
? ? ?Parent.apply(this);
? ? ?this.name=name;
? ? ?this.age=age;
?}
Sub.prototype=new Parent('父親',45);
?var? sub=new Sub('小明',11);
?var? sub1=new Sub('小紅',12);
?console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);true;
// 優(yōu)點(diǎn):
?可以繼承多個(gè)父類瞭恰;
?既可以繼承父類構(gòu)造函數(shù)里面屬性和方法屯曹,又可以繼承父類原型屬性和方法;
?函數(shù)可以復(fù)用惊畏;
?父類的引用值不會(huì)共享恶耽;
// 缺點(diǎn):
?調(diào)用了兩次父類的構(gòu)造函數(shù),產(chǎn)生了兩份父類實(shí)例颜启,多消耗了一點(diǎn)內(nèi)存偷俭。
第四種. 循環(huán)拷貝繼承
?function Sub(name,age) {
? ? ?var parent=new Parent(name,age);
? ? ?for(var prop in parent){
? ? ? ? ?Sub.prototype[prop]=parent[prop];
? ? ?}
?}
?var? sub=new Sub('小紅',12);
?console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);false;
// 優(yōu)點(diǎn):
?可以繼承多個(gè)父類;
可以將父類的所有屬性和方法均繼承下來(lái)缰盏;
// 缺點(diǎn):
?效率較低涌萤;
?實(shí)例不屬于父類的實(shí)例。
//第五種:循環(huán)拷貝+構(gòu)造函數(shù)
?function Sub(name,age) {
? ? Parent.call(this,name,age);
?}
?for(var prop in Parent.prototype){
? ? ?Sub.prototype[prop]=Parent.prototype[prop];
?}
?var? sub=new Sub('小紅',12);
console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);false;
// 優(yōu)點(diǎn):
?可以繼承多個(gè)父類口猜;
可以將父類的所有屬性和方法均繼承下來(lái)负溪;
// 缺點(diǎn):
?效率較低;
實(shí)例不屬于父類的實(shí)例
第六種:共享原型
?function Sub(name,age) {
?Parent.call(this,name,age);
? ?this.name=name;
? ? ?this.age=age;
?}
?Sub.prototype=Parent.prototype;
var? sub=new Sub('小明',11);
?console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);true;
// 優(yōu)點(diǎn):
最簡(jiǎn)單的繼承方式之一济炎;
// 缺點(diǎn):
只能繼承父類原型屬性方法川抡,不能繼承父類構(gòu)造函數(shù)的屬性方法;//可以使用構(gòu)造函數(shù)繼承,解決這個(gè)問(wèn)題
?子類共享原型上的引用屬性
第七種:圣杯模式
?function Sub(name,age){
? ? ?Parent.call(this,name,age);
?}
?function inherit(sub,parent){
? ? ?function Temp(){}
? ? ?Temp.prototype=parent.prototype;
? ? ?sub.prototype=new Temp();
? ? ?sub.prototype.constructor=Parent;
? ? ?sub.prototype.uber=Parent;
?}
?inherit(Sub,Parent);
?var? sub=new Sub('小明',11);
?console.log(sub instanceof Sub); true;
?console.log(sub instanceof Parent);true;
// 優(yōu)點(diǎn):
?堪稱完美冻辩;
// 缺點(diǎn):
?實(shí)現(xiàn)復(fù)雜猖腕;
不能實(shí)現(xiàn)多繼承。
// 總結(jié):
?繼承實(shí)現(xiàn)方法很多恨闪,最好的繼承方式是圣杯模式的繼承和js循環(huán)拷貝兩種倘感,需要注意的是圣杯模式繼承不能實(shí)現(xiàn)繼承多個(gè)父類,只有循環(huán)拷貝繼承才可以很完美的實(shí)現(xiàn)繼承多個(gè)父類咙咽。
//ES6三種繼承模式
?AttackPlane.prototype.__proto__=Plan.prototype;//慎用
?AttackPlane.prototype=Object.create(Plane.prototype,function(){
? ? ?constructor:AttackPlane;//修改構(gòu)造函數(shù)
?})
?Object.setPrototypeOf(AttackPlane.prototype,Plane.prototype);//ES6,推薦