乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      淺談JavaScript類的繼承

       歪SIR 2011-09-19
      利用共享prototype實現(xiàn)繼承
      繼承是面向對象開發(fā)的又一個重要概念,它可以將現(xiàn)實生活的概念對應到程序邏輯中。例如水果是一個類,具有一些公共的性質;而蘋果也是一類,但它們屬于水果,所以蘋果應該繼承于水果。powered by 25175.net
      在JavaScript中沒有專門的機制來實現(xiàn)類的繼承,但可以通過拷貝一個類的prototype到另外一個類來實現(xiàn)繼承。一種簡單的實現(xiàn)如下:
      fucntion class1(){
            //構造函數(shù)
      }

      function class2(){
            //構造函數(shù)
      }
      class2.prototype=class1.prototype;
      class2.prototype.moreProperty1="xxx";
      class2.prototype.moreMethod1=function(){
            //方法實現(xiàn)代碼
      }
      var obj=new class2();
      這樣,首先是class2具有了和class1一樣的prototype,不考慮構造函數(shù),兩個類是等價的。隨后,又通過prototype給class2賦予了兩個額外的方法。所以class2是在class1的基礎上增加了屬性和方法,這就實現(xiàn)了類的繼承。
      JavaScript提供了instanceof操作符來判斷一個對象是否是某個類的實例,對于上面創(chuàng)建的obj對象,下面兩條語句都是成立的:
      obj instanceof class1
      obj instanceof class2
      表 面上看,上面的實現(xiàn)完全可行,JavaScript也能夠正確的理解這種繼承關系,obj同時是class1和class2的實例。事是上不 對,JavaScript的這種理解實際上是基于一種很簡單的策略??聪旅娴拇a,先使用prototype讓class2繼承于class1,再在 class2中重復定義method方法:
      <script language="JavaScript" type="text/javascript">
      <!--
      //定義class1
      function class1(){
            //構造函數(shù)
      }
      //定義class1的成員
      class1.prototype={
            m1:function(){
                  alert(1);
            }
      }
      //定義class2
      function class2(){
            //構造函數(shù)
      }
      //讓class2繼承于class1
      class2.prototype=class1.prototype;
      //給class2重復定義方法method
      class2.prototype.method=function(){
            alert(2);
      }
      //創(chuàng)建兩個類的實例
      var obj1=new class1();
      var obj2=new class2();
      //分別調用兩個對象的method方法
      obj1.method();
      obj2.method();
      //-->
      </script>
      從 代碼執(zhí)行結果看,彈出了兩次對話框“2”。由此可見,當對class2進行prototype的改變時,class1的prototype也隨之改變,即 使對class2的prototype增減一些成員,class1的成員也隨之改變。所以class1和class2僅僅是構造函數(shù)不同的兩個類,它們保 持著相同的成員定義。從這里,相信讀者已經發(fā)現(xiàn)了其中的奧妙:class1和class2的prototype是完全相同的,是對同一個對象的引用。其實 從這條賦值語句就可以看出來:
      //讓class2繼承于class1
      class2.prototype=class1.prototype;
      在 JavaScript中,除了基本的數(shù)據(jù)類型(數(shù)字、字符串、布爾等),所有的賦值以及函數(shù)參數(shù)都是引用傳遞,而不是值傳遞。所以上面的語句僅僅是讓 class2的prototype對象引用class1的prototype,造成了類成員定義始終保持一致的效果。從這里也看到了instanceof 操作符的執(zhí)行機制,它就是判斷一個對象是否是一個prototype的實例,因為這里的obj1和obj2都是對應于同一個prototype,所以它們 instanceof的結果都是相同的。
      因此,使用prototype引用拷貝實現(xiàn)繼承不是一種正確的辦法。但在要求不嚴格的情況下,卻也是一種合理的方法,惟一的約束是不允許類成員的覆蓋定義。下面一節(jié),將利用反射機制和prototype來實現(xiàn)正確的類繼承。
      利用反射機制和prototype實現(xiàn)繼承
      前 面一節(jié)介紹的共享prototype來實現(xiàn)類的繼承,不是一種很好的方法,畢竟兩個類是共享的一個prototype,任何對成員的重定義都會互相影響, 不是嚴格意義的繼承。但在這個思想的基礎上,可以利用反射機制來實現(xiàn)類的繼承,思路如下:利用for(…in…)語句枚舉出所有基類prototype的 成員,并將其賦值給子類的prototype對象。例如:
      <script language="JavaScript" type="text/javascript">
      <!--
      function class1(){
            //構造函數(shù)
      }
      class1.prototype={
            method:function(){
                 alert(1);
            },
            method2:function(){
                 alert("method2");
            }
      }
      function class2(){
            //構造函數(shù)
      }
      //讓class2繼承于class1
      for(var p in class1.prototype){
             class2.prototype[p]=class1.prototype[p];
      }

      //覆蓋定義class1中的method方法
      class2.prototype.method=function(){
            alert(2);
      }
      //創(chuàng)建兩個類的實例
      var obj1=new class1();
      var obj2=new class2();
      //分別調用obj1和obj2的method方法
      obj1.method();
      obj2.method();
      //分別調用obj1和obj2的method2方法
      obj1.method2();
      obj2.method2();
      //-->
      </script>
      從 運行結果可見,obj2中重復定義的method已經覆蓋了繼承的method方法,同時method2方法未受影響。而且obj1中的method方法 仍然保持了原有的定義。這樣,就實現(xiàn)了正確意義的類的繼承。為了方便開發(fā),可以為每個類添加一個共有的方法,用以實現(xiàn)類的繼承:
      //為類添加靜態(tài)方法inherit表示繼承于某類
      Function.prototype.inherit=function(baseClass){
           for(var p in baseClass.prototype){
                  this.prototype[p]=baseClass.prototype[p];
           }
      }
      這里使用所有函數(shù)對象(類)的共同類Function來添加繼承方法,這樣所有的類都會有一個inherit方法,用以實現(xiàn)繼承,讀者可以仔細理解這種用法。于是,上面代碼中的:
      //讓class2繼承于class1
      for(var p in class1.prototype){
             class2.prototype[p]=class1.prototype[p];
      }
      可以改寫為:
      //讓class2繼承于class1
      class2.inherit(class1)
      這樣代碼邏輯變的更加清楚,也更容易理解。通過這種方法實現(xiàn)的繼承,有一個缺點,就是在class2中添加類成員定義時,不能給prototype直接賦值,而只能對其屬性進行賦值,例如不能寫為:
      class2.prototype={
            //成員定義
      }
      而只能寫為:
      class2.prototype.propertyName=someValue;
      class2.prototype.methodName=function(){
            //語句
      }
      由 此可見,這樣實現(xiàn)繼承仍然要以犧牲一定的代碼可讀性為代價,在下一節(jié)將介紹prototype-1.3.1框架(注:prototype-1.3.1框架 是一個JavaScript類庫,擴展了基本對象功能,并提供了實用工具詳見附錄。)中實現(xiàn)的類的繼承機制,不僅基類可以用對象直接賦值給 property,而且在派生類中也可以同樣實現(xiàn),使代碼邏輯更加清晰,也更能體現(xiàn)面向對象的語言特點。

      prototype-1.3.1框架中的類繼承實現(xiàn)機制
      在prototype-1.3.1框架中,首先為每個對象都定義了一個extend方法:
      //為Object類添加靜態(tài)方法:extend
      Object.extend = function(destination, source) {
        for(property in source) {
           destination[property] = source[property];
        }
        return destination;
      }
      //通過Object類為每個對象添加方法extend
      Object.prototype.extend = function(object) {
        return Object.extend.apply(this, [this, object]);
      }
      Object.extend 方法很容易理解,它是Object類的一個靜態(tài)方法,用于將參數(shù)中source的所有屬性都賦值到destination對象中,并返回 destination的引用。下面解釋一下Object.prototype.extend的實現(xiàn),因為Object是所有對象的基類,所以這里是為所 有的對象都添加一個extend方法,函數(shù)體中的語句如下:
      Object.extend.apply(this,[this,object]);
      這 一句是將Object類的靜態(tài)方法作為對象的方法運行,第一個參數(shù)this是指向對象實例自身;第二個參數(shù)是一個數(shù)組,包括兩個元素:對象本身和傳進來的 對象參數(shù)object。函數(shù)功能是將參數(shù)對象object的所有屬性和方法賦值給調用該方法的對象自身,并返回自身的引用。有了這個方法,下面看類繼承的 實現(xiàn):
      <script language="JavaScript" type="text/javascript">
      <!--
      //定義extend方法
      Object.extend = function(destination, source) {
        for (property in source) {
           destination[property] = source[property];
        }
        return destination;
      }
      Object.prototype.extend = function(object) {
        return Object.extend.apply(this, [this, object]);
      }
      //定義class1
      function class1(){
            //構造函數(shù)
      }
      //定義類class1的成員
      class1.prototype={
            method:function(){
                 alert("class1");
            },
            method2:function(){
                 alert("method2");
            }

      }
      //定義class2
      function class2(){
            //構造函數(shù)
      }
      //讓class2繼承于class1并定義新成員
      class2.prototype=(new class1()).extend({
            method:function(){
                 alert("class2");
            }
      });

      //創(chuàng)建兩個實例
      var obj1=new class1();
      var obj2=new class2();
      //試驗obj1和obj2的方法
      obj1.method();
      obj2.method();
      obj1.method2();
      obj2.method2();
      //-->
      </script>
      從運行結果可以看出,繼承被正確的實現(xiàn)了,而且派生類的額外成員也可以以列表的形式加以定義,提高了代碼的可讀性。下面解釋繼承的實現(xiàn):
      //讓class2繼承于class1并定義新成員
      class2.prototype=(new class1()).extend({
            method:function(){
                 alert("class2");
            }
      });
      上段代碼也可以寫為:
      //讓class2繼承于class1并定義新成員
      class2.prototype=class1.prototype.extend({
            method:function(){
                 alert("class2");
            }
      });
      但 因為extend方法會改變調用該方法對象本身,所以上述調用會改變class1的prototype的值,犯了和以前一樣的錯誤。在 prototype-1.3.1框架中,巧妙的利用new class1()來創(chuàng)建一個實例對象,并將實例對象的成員賦值給class2的prototype。其本質相當于創(chuàng)建了class1的prototype 的一個拷貝,在這個拷貝上進行操作自然不會影響原有類中prototype的定義了。

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多