寄生組合繼承稱爲完美繼承(其餘繼承方式都有缺陷)html
如下爲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種繼承的詳細寫法。this
原形鏈繼承prototype
//原形鏈繼承 //父類 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();(只有一句話)
借用構造函數繼承code
//借用構造函數繼承 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指向的轉變和參數的傳遞。
組合繼承htm
//組合繼承 //父類 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
寄生式繼承ip
//寄生式繼承 //經過該方法,爲子類添加方法,以實現繼承;(即加強子類) 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();
寄生組合繼承(又稱完美繼承)get
//寄生組合繼承 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();
另外,你能夠將Super一、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>