首頁 >web前端 >js教程 >詳解JavaScript繼承

詳解JavaScript繼承

黄舟
黄舟原創
2017-02-27 14:37:581339瀏覽

在正式討論js繼承之前,先說說自己的工作體會。不像後端,對於大多數商業應用場景,對前端的要求往往會導致程式碼難以上溯(指難以抽象,難以寫一遍程式碼在好幾個場景都適用)。說我熟悉的應用場景:例如一個信用評級模組,一個頁面用一個折線圖顯示用戶最近的消費水平,另一個頁面用一個折線圖展示用戶的信用評級水平。看似很相似的需求吧?拿到java裡肯定抽像出一個「折線圖介面「了吧,但是在js裡就很難統一。首先,這兩個資料來源不同,那麼ajax請求的程式碼就天差地別。其次,UI隨便給一個圖加個陰影、漸變色之類的圖形效果,兩個圖的實作就會完全不同。不僅如此,如果你為了展現自己的設計水平,強行把兩塊有差別的前端實現整合在一起,你將會面對常人不會面對到的維護噩夢。因此,對於大部分前端工程師而言,沒有了解JavaScript繼承的需求,這個語言的這個功能也確實沒有一個很大眾化的應用場景,當然如果你在寫某些底層框架,那你一定會很了解這些特性。以下內容難度中上,我稍微改寫了一點《JavaScript高級程式設計》當中的繼承,然後放了一段jQuery當中的繼承模型優化版,以後有時間有精力再補充文字說明吧,不感興趣的可以直接過了~


1)組合繼承(combination inheritance):

在子類別建構子中透過Super.call(this)來新增父類別的屬性,並且透過讓子類別建構子的prototype成為父類別的實例來實現繼承。缺點是會在子類別建構函式中儲存冗餘的父類別屬性(因為他是父類別的一個實例,而子類別的實例又會覆寫一次同樣的屬性),同時會呼叫兩次父類別的建構函數,而且也會導致繼承鏈多了一層。


(function combineInherit(){
   function SuperType(){
      this.super="super";
   }
   SuperType.prototype.saySuper=function(){

   }

   function SubType(){
      SuperType.call(this,arguments);
      this.sub="sub";
   }
   SubType.prototype=new SuperType();
   SubType.prototype.constructor=SubType;
   SubType.prototype.saySub=function(){

   }

   var sub1=new SubType();
   sub1.saySub();
})();


繼承鏈:

 

##(2)寄生組合式繼承(parasitic combination inheritance):

與組合繼承不同在於,寄生組合式繼承另子類別建構子的prototype不成為父類別的實例,而是直接透過父類別建構子的prototype的引用來形成子類別建構子的prototype,最精簡的方式就是另二者直接等同,這不僅減少了一次父類別建構子的調用,減少了存在子類別prototype中的冗餘屬性,同樣也減少了一層繼承鏈(並且在這種情況下用instanceof判斷仍然同屬子類別和父類別)。

(function parasiticCombineInherit(){
   function inheritPrototype(subType,superType){
      subType.prototype=superType.prototype;
      subType.prototype.constructor=subType;
   }

   function SuperType(){
      this.super="super";
   }
   SuperType.prototype.saySuper=function(){

   }

   function SubType(){
      SuperType.call(this,arguments);
      this.sub="sub";
   }
   inheritPrototype(SubType,SuperType);
   SubType.prototype.saySub=function(){

   }

   var sub=new SubType();
   console.log(sub instanceof SuperType);
})();


繼承鏈:

 

##(

3jQUery式經典繼承

#

(function classicInherit(){
   var initializing=false,
      superPattern=/xyz/.test(function() {xyz;}) ? /\b_super\b/ : /.*/;
   Object.subClass=function(properties){
      var _super=this.prototype;
      initializing=true;
      var proto=new this();
      initializing=false;

      for(var name in properties){
         proto[name]=typeof properties[name]=="function"&&
                  typeof _super[name]=="function"&&
                  superPattern.test(properties[name])?
               (function(name,fn){
                  return function(){
                     var tmp=this._super;
                     this._super=_super[name];
                     var ret=fn.apply(this,arguments);
                     this._super=tmp;
                     return ret;
                  };
               })(name,properties[name]):properties[name];
      }

      function Class(){
         //init方法需要通过外部自定义传入
         if(!initializing&&this.init){
            this.init.apply(this,arguments);
         }
      }
      Class.prototype=proto;
      Class.constructor=Class;
      Class.subClass=arguments.callee;

      return Class;
   }
})();

 以上就是詳解JavaScript繼承的內容,更多相關內容請關注PHP中文網(www.php.cn)!



#

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn