自知其無知
          不懂,慢慢懂。
          posts - 2,comments - 2,trackbacks - 0


          <script>
               
             
          // 一個有趣的現象,也是一個值得分析的區別:
             Object.extend = function (destination,source){
                  
          // 首先,這個循環很奇妙,這個 property 是什么? 數組下標?
                  
                  
          for(property in source){
                      
                      destination[property] 
          = source[property];
                  }
                  

                  
          return destination;
             }

             

             
          // 那么這里的 Object.extend 與 Object.prototype.extend 的區別是什么?
             // Object.extend 是屬于類本身,而 Object.prototype.extend 所定義的方法屬于所有的繼承類?
             Object.prototype.extend = function (object){
                
          return Object.extend.apply(this,[this,object]);
             }


             
          /*
                這里 extend 函數是為所有派生自 Object 的子類添加 extend 方法
                1. 你可以把 extend 理解為 Object 靜態方法  ,也就是 Object.extend ,是 Object 本身獨有的
                2. 是 Object 添加 extend 公用方法,而他本身就是調用 Object.extend() 的,然后使用 apply 使得
                   調用函數執行范圍在 object.prototype 里,而不是 Object 自己,否則以后從 Object 或其派生
                   類創建出的實例得不到 extend 中傳入的參數的,這里 apply 的第一個參數就是 Object.prototype
                   第二個參數是第一個方法的參數
                3. 是 extend 方法的應用
              
          */


              
          /*
                來寫一個例子來驗證說法是否正確:(也就是如果不用 apply ,那么以后從)
              
          */



             
          // 驗證循環的奇妙現象
             var arr = new Array("China","England","USA");
             
          for(obj in arr){
                
                alert(obj); 
          // output  "0","1","2" ,也就是數組的下標
             }


            
          //定義一個抽象基類base,無構造函數 (嚴格的說,base 類是不能被實例化的,但是我們卻可以不規范的實例化,比如 (1) 所示)
              function base(){}
              
              
          /* 
                 通過 base.prototype = {} 以及 base.prototype.oninit = function(){} 兩種方式我們可以看到,prototype 本身就
                 是一個對象,而一個對象的賦值方式可以有兩種形式,一種,就是用 key : value 的形式,也就是
                 base.protype = {
                   key : value 
                 }
                 而另一種形式就是 直接賦值的形式,也就是  base.protype.key = value 
                 也就是說 obj = {
                     key : value
                  }
                  和 obj.key = value 
                  是等價的
               
          */

              base.prototype
          ={
                    initialize:
          function(){
                             
          this.oninit(); //調用了一個虛方法 
                    }

              }
            

              
          /*****  base 類不規范的實例化(解釋性的語言就是這樣,呵呵) ********/
              
          /*  
              base.prototype.oninit = function (){
                  alert('方法 oninit() 被調用');
              }
              
          */

            
          //  var ba = new base(); // base 被實例化了(關鍵點是,只要在調用的時候,oninit()方法被定義出來了就行!)
              
              
          // 讓一個 class 繼承于 base 并實現其中的 oninit 方法
              function class1(){}
              
              class1.prototype 
          = (new base()).extend(
                  
          {
                      oninit : 
          function (){  // 實現抽象基類的 oninit 虛方法           
                              // oninit 函數實現
                      }

                  }

              );
              
              
          var cs = new class1();
              alert(cs 
          instanceof base);    //  竟然能夠 ouput "true"
              /*   */
             
          /* 這樣,當在 class1 實例中調用繼承得到 initialize 方法時,就會自動執行派生類中的 oninit() 方法。
                從這里也可以看到解釋型語言執行的特點,它們只有運行到某一個方法調用時,才會檢查該方法是否存在,
                而不會像編譯型語言一樣,在編譯階段就檢查方法是否存在, JavaScript 中則避免了這個問題,當然,如
                過希望在虛類中添加虛方法的一個定義,也是可以的。只要在派生類中覆蓋此方法即可.

                例如,定義一個抽象基類  base1,無構造函數
              
          */
           
              
          function base1(){}
              base1.prototype 
          = {
                  initilize:
          function(){
                      
          this.oninit();  // 這里調用了一個虛方法
                  }
          ,
                  oninit : 
          function(){} // 虛方法是一個空方法,由派生類產生
              }

              
             
          /**********************************************************************************/
             
          /* 使用抽象類的示例:  */
             
          /*
                仍然以 prototype-1.3.1 為例,其中定義了一個類的創建模型:
             
          */

             
          // Class1 是一個全局對象,有一個方法 create ,用于返回一個類,
             var Class1 = {
                create : 
          function (){
                  
          return function (){
                      
          this.initialize.apply(this,arguments);
                  }

                }

             }

             
          /*
                 這里 Class1 是一個全局對象,具有一個方法 create,用于返回一個函數(類),可以用如下
                 語法:
              
          */

              
          var c1 = Class1.create();
              
          /*
                這樣定義類的方式就和定義函數的方式區分開來,使 JavaScript 語言更具備面向對象的特點。現在
                來看這個返回的函數(類):
                function (){
                   this.initilize.apply(this,arguments);
                }
                這個函數也是一個類的構造函數,當 new 這個類的時候便會執行,他調用了一個 initilize() 的方法,
                從名字看來,是類的構造函數。從類的角度來看,它是一個虛方法,是未定義的。但這個虛方法的實現
                并不是在派生類中實現的,而是創建完一個類后,在 prototype 中定義的,例如 prototype 可以這樣
                寫:
                var c1 = Class.create();
                c1.protype = {
                   initilize : function( userName ){
                       alert('hello,' + userName);
                   }
                }

                這樣,每次創建類的實例的時候,initialize 方法都會得到執行。從而實現了將類的構造函數和類成員一起
                定義的功能。其中,為了能夠給構造函數傳遞參數,使用了這樣的語句。
                function (){
                   this.initilize.apply(this,arguments);
                }

                實際上,這里的 arguments 是 function() 中所傳進來的參數,也就是 new class1(args) 中傳遞進來的參數,
                現在要把 args 傳遞給 initilize ,巧妙的使用了 apply() ,注意不能寫成:
                this.initilize(arguments);

                這是將 arguments 數組作為一個參數傳遞給 initilize() 方法,而 apply() 方法則可以將 arguments() 對象
                的元素作為一組參數傳遞過去,這是一個很巧妙的實現。
                盡管這個例子在 prototype-1.3.1 中不是一個抽象類的概念,而是類的一種設計模式。但實際上,可以把
                 Class.create() 返回的類看做所有類的共同基類,它在構造函數中調用了一個虛方法 initilize ,所有繼承
                 于它的類都必須實現這個方法,完成構造函數的功能。它們得以實現的本質就是對 prototype 的操作.
               
          */


          </script>
          posted on 2008-12-07 18:23 CopyHoo 閱讀(1557) 評論(0)  編輯  收藏 所屬分類: JavaScript
          主站蜘蛛池模板: 沙雅县| 闸北区| 上林县| 建湖县| 宁波市| 巴彦县| 仁寿县| 武定县| 嘉兴市| 沁水县| 垦利县| 富宁县| 苗栗县| 龙胜| 嘉兴市| 怀远县| 东港市| 新民市| 晋江市| 饶河县| 竹北市| 满洲里市| 磴口县| 宁夏| 沛县| 定州市| 南郑县| 西平县| 尉氏县| 兴安盟| 石渠县| 肥东县| 云南省| 通榆县| 六枝特区| 东兰县| 杨浦区| 慈利县| 长阳| 玉环县| 淅川县|