//js各種繼承的分析;
function Parent(name,age){
this.name=name;
? ? ? this.age=age;
? ? ? this.money=100;
? ? ? this.fly=function(){
console.log('這是對象本身的fly方法');
? ? ? }
}
Parent.prototype.sex='male';
Parent.prototype.play=function(){
console.log('這是原型上面的play方法');
}
var parent=new Parent('父親',45);
//1:第一種:原型指向父類實例
?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)點:
?這是一個非常純粹的繼承,實例是子類的實例,也屬于父級的實例,父類的屬性方法以及父類原型上添加的屬性或方法,子類都可以訪問得到;
?缺點:
?原型對象上的引用屬性,所有的實例都是共享的,即在一個實例上修改,所有的實例均跟著變化;
?不能同時繼承多個父類。
第二種:構(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)點:
?這種繼承方式解決了傳統(tǒng)繼承中共享引用屬性的問題;
?創(chuàng)建子類實例的時候可以向父級傳遞參數(shù);
?可以繼承多個父類;
// 缺點:
/只能繼承父類構(gòu)造函數(shù)里面的屬性方法,不會繼承父類原型上的屬性方法;
無法實現(xiàn)函數(shù)復(fù)用,每個子類都有父類實例的副本,影響性能;
?實例只是子類的實例不是父類的實例。
第三種:原型指向父類實例+構(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)點:
?可以繼承多個父類;
?既可以繼承父類構(gòu)造函數(shù)里面屬性和方法,又可以繼承父類原型屬性和方法;
?函數(shù)可以復(fù)用;
?父類的引用值不會共享;
// 缺點:
?調(diào)用了兩次父類的構(gòu)造函數(shù),產(chǎ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)點:
?可以繼承多個父類;
可以將父類的所有屬性和方法均繼承下來;
// 缺點:
?效率較低;
?實例不屬于父類的實例。
//第五種:循環(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)點:
?可以繼承多個父類;
可以將父類的所有屬性和方法均繼承下來;
// 缺點:
?效率較低;
實例不屬于父類的實例
第六種:共享原型
?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)點:
最簡單的繼承方式之一;
// 缺點:
只能繼承父類原型屬性方法,不能繼承父類構(gòu)造函數(shù)的屬性方法;//可以使用構(gòu)造函數(shù)繼承,解決這個問題
?子類共享原型上的引用屬性
第七種:圣杯模式
?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)點:
?堪稱完美;
// 缺點:
?實現(xiàn)復(fù)雜;
不能實現(xiàn)多繼承。
// 總結(jié):
?繼承實現(xiàn)方法很多,最好的繼承方式是圣杯模式的繼承和js循環(huán)拷貝兩種,需要注意的是圣杯模式繼承不能實現(xiàn)繼承多個父類,只有循環(huán)拷貝繼承才可以很完美的實現(xiàn)繼承多個父類。
//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,推薦