標籤:javascript web web開發
繼承是物件導向中一個比較核心的概念。 其他正統物件導向語言都會用兩種方式實現繼承:一個是介面實現,一個是繼承。而 ECMAScript 只支援繼承,不支援介面實現,而實現繼承的方式依靠原型鏈完成。在JavaScript中的繼承中,分了好幾類繼承,可以說是伴隨著問題的出現,繼承的方法也升級了,不光是原型鏈繼承,還有組合繼承、原型繼承、寄生式繼承、寄生組合繼承等等。他們伴隨著不同問題的出現而出現,下面我分別介紹一下這幾種繼承方式。
1、原型鏈式繼承
<span style="font-family:KaiTi_GB2312;font-size:18px;">function Box() { //Box 構造this.name = '美女';}function Desk() { //Desk 構造this.age = 100;}Desk.prototype = new Box(); //Desk 繼承了 Box,通過原型,形成鏈條var desk = new Desk();alert(desk.age);alert(desk.name); //得到被繼承的屬性</span> 缺點:原型鏈式繼承執行個體化後的初始值是一樣的,不能改變,也無法複用,組合繼承(原型鏈+借用建構函式)來解決這種問題。
2、組合繼承(原型鏈+借用建構函式)
<span style="font-family:KaiTi_GB2312;font-size:18px;">function Box(age){this.name=['林志玲','範冰冰'];this.age=age;}Box.prototype.run=function(){return this.name+'的年齡是'+this.age;}function Desk(age){Box.call(this,age); //對象冒充,這裡的作用是傳遞參數,只會講Box的執行個體中的方法和屬性傳遞給Desk(),原型中的資訊不會傳遞。}// var desk=new Desk(20);// alert(desk.name+'你們好嗎???'); //這裡返回 林志玲,範冰冰你們好嗎??? 原因是Desk()函數內部使用了對象冒充。// alert(desk.run()); //沒有設定原型鏈繼承,run()方法不會被繼承下來。Desk.prototype=new Box(); //使用原型鏈繼承,將Box()的原型和執行個體的所有資訊都傳給Desk()var desk=new Desk(20);alert(desk.name+'你們好嗎???'); //返回 林志玲,範冰冰你們好嗎???alert(desk.run()); //返回 林志玲,範冰冰的年齡是 20</span>
組合繼承的彌補了原型鏈式繼承穿參和共用問題,但是缺點是每次執行個體化一個對象的執行個體,都需要兩次調用超類Box().而寄生組合繼承就能解決此問題。寄生組合繼承一會在說,先說一下原型式繼承。
3、 原型式繼承
<span style="font-family:KaiTi_GB2312;font-size:18px;">//function obj(o) { //傳遞一個字面量函數function F() {} //建立一個建構函式F.prototype = o; //把字面量函數賦值給建構函式的原型return new F(); //最終返回出執行個體化的建構函式}var box = { //字面量對象name : 'Lee',arr : ['哥哥','妹妹','姐姐'] //添加一個數組,數組時參考型別};var box1 = obj(box); //傳遞alert(box1.name); //返回Leebox1.name = 'Jack'; //將name改成jackalert(box1.name); //返回Jackalert(box1.arr);box1.arr.push('父母'); //arr屬性是一個數組,這裡往數組裡多添加一個父母。alert(box1.arr);var box2 = obj(box); //傳遞alert(box2.name); //返回Lee,而不是Jack,子類之間,實值型別沒有共用。alert(box2.arr); //返回哥哥,妹妹,姐姐,父母,子類之間,參考型別共用了。</span> 這種繼承藉助原型並基於已有的對象建立新對象執行個體,同時還不必因此建立自訂類型(不用自己添加屬性和方法)。
4、寄生式繼承(原型繼承+Factory 方法模式)
<span style="font-family:KaiTi_GB2312;font-size:18px;">function obj(o){function F(){}F.prototype=o;return new F();}function create(o){f=obj(o)f.run=function(){return this.family;}return f;}var box={name:'林志穎',age:22,family:['參考型別1']}var box1 = create(box); //傳遞alert(box1.name); //繼承的是box對象,輸出 林志穎box1.name='劉亦菲'; //將自己執行個體中name屬性改成劉亦菲,更改的是子類型的namealert(box1.name); //輸出劉亦菲alert(box1.run()); //輸出的是參考型別1,box1.family.push('參考型別2');//輸出的是參考型別1,參考型別2,更改的是超類型的familyalert(box1.run());var box2 = create(box); //傳遞alert(box2.name); //繼承的是box對象,輸出 林志穎 並沒有輸出劉亦菲alert(box2.run()); </span> 寄生式繼承把原型式+原廠模式結合而來,目的是為了封裝建立對象的過程。
5、寄生組合繼承 解決多次執行個體化時,多次調用超類問題。
<span style="font-family:KaiTi_GB2312;font-size:18px;">//中轉函數function obj(o){function F(){}F.prototype=o;return new F();}//寄生函數function create(box,desk){f=obj(box.prototype); //這裡傳的是Box的原型對象f.constructor=desk; //調整原型指標desk.prototype=f;}function Box(name,age){this.name=name;this.age=age;}Box.prototype.run=function(){return this.name+this.age;}function Desk(name,age){Box.call(this,name,age); //對象冒充調用,在這裡也是傳遞參數的作用。}//通過寄生組合來實現繼承create(Box,Desk); //替代Desk.prototype=new Box();var desk=new Desk('美女',25)alert(desk.run()); //返回美女,25</span> 小結
這幾種繼承方式都介紹完了,我只是瞭解到皮毛,但是它們在項目中的真正作用哪怕只有在鍛煉項目時才會發現,現在說什麼都是嘴把式,再有真把式之前,這些理論知識也是很有必要的,就讓項目再升華這幾種繼承方式吧!
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
《JavaScript》——物件導向之繼承