乖,別哭的薄殼
          ~一份耕耘,一份收獲~
          posts - 23,comments - 260,trackbacks - 0

          一、繼承的方式
          1.對象冒充
          function ClassA(sColor) {
              this.color = sColor;
              this.sayColor = function () {
                  alert(this.color);
              };
          }

          function ClassB(sColor, sName) {
              this.newMethod = ClassA;
              this.newMethod(sColor);
              delete this.newMethod;
             
              this.name = sName;
              this.sayName = function () {
                  alert(this.name);
              };   
          }

          var objA = new ClassA("red");
          var objB = new ClassB("blue", "Nicholas");
          objA.sayColor();
          objB.sayColor();
          objB.sayName();
          所有新的屬性和新的方法都必須在刪除了新方法的代碼行后定義。否則,可能會覆蓋超類的相關屬性和方法。
          對象冒充可以支持多繼承。
          function ClassZ(){
             this.newMethod = ClassX;
             this.newMethod(sColor);
             delete this.newMethod;

             this.newMethod = ClassY;
             this.newMethod(sColor);
             delete this.newMethod;
          }
          這里存在一個弊端,如果ClassX和ClassY具有相同的屬性或方法,ClassY具有高優先級,因為繼承的是最后的類。

          2.call()方法
          call()方法是與經典的對象冒充方法最相似的方法,它的第一個參數用作this的對象,其他參數都直接傳遞函數自身。
          function ClassA(sColor) {
              this.color = sColor;
              this.sayColor = function () {
                  alert(this.color);
              };
          }

          function ClassB(sColor, sName) {
              //this.newMethod = ClassA;
              //this.newMethod(color);
              //delete this.newMethod;
              ClassA.call(this, sColor);

              this.name = sName;
              this.sayName = function () {
                  alert(this.name);
              };
          }

          var objA = new ClassA("red");
          var objB = new ClassB("blue", "Nicholas");
          objA.sayColor();
          objB.sayColor();
          objB.sayName();

          3.apply()方法
          apply()方法有兩個參數,用作this的對象和要傳遞參數的數組。例如:
          function ClassA(sColor) {
              this.color = sColor;
              this.sayColor = function () {
                  alert(this.color);
              };
          }

          function ClassB(sColor, sName) {
              //this.newMethod = ClassA;
              //this.newMethod(color);
              //delete this.newMethod;
              ClassA.apply(this, arguments);

              this.name = sName;
              this.sayName = function () {
                  alert(this.name);
              };
          }

          var objA = new ClassA("red");
          var objB = new ClassB("blue", "Nicholas");
          objA.sayColor();
          objB.sayColor();
          objB.sayName();

          當然,只有超類中的參數順序與子類中的參數順序完全一致時才可以傳遞參數對象。如果不是,就必須創建一個單獨的數組,按照正確的順序放置參數。此外,還可以使用call()方法。

          4.原型鏈
          function ClassA() {
          }

          ClassA.prototype.color = "red";
          ClassA.prototype.sayColor = function () {
              alert(this.color);
          };

          function ClassB() {
          }

          ClassB.prototype = new ClassA();

          ClassB.prototype.name = "";
          ClassB.prototype.sayName = function () {
              alert(this.name);
          };

          var objA = new ClassA();
          var objB = new ClassB();
          objA.color = "red";
          objB.color = "blue";
          objB.name = "Nicholas";
          objA.sayColor();
          objB.sayColor();
          objB.sayName();
          注意,調用ClassA的構造函數時,沒有給它傳遞參數。這在原型鏈中是標準做法。要確保構造函數沒有任何參數。
          原型鏈的弊端是不支持多重繼承。

          5.混合方式
          與創建對象最好方式相似,用對象冒充繼承構造函數的屬性,用原型鏈繼承prototype對象的方法。
          function ClassA(sColor) {
              this.color = sColor;
          }

          ClassA.prototype.sayColor = function () {
              alert(this.color);
          };

          function ClassB(sColor, sName) {
              ClassA.call(this, sColor);
              this.name = sName;
          }

          ClassB.prototype = new ClassA();

          ClassB.prototype.sayName = function () {
              alert(this.name);
          };


          var objA = new ClassA("red");
          var objB = new ClassB("blue", "Nicholas");
          objA.sayColor();
          objB.sayColor();
          objB.sayName();


          二、其他繼承方式
          1.zlnherit庫
          可以從http://www.nczonline.net/downloads處下載
          zInherit庫給Object類添加了兩個方法,inheritFrom()和instanceOf()
          ClassB.prototype.inheritFrom(ClassA);
          CalssB.instanceOf(ClassA);

          2.xbObjects庫
          可以從         這里,子類和超類名都以字符串形式傳進來,而不是指向它們的構造函數的指針。這個調用必須放在指定子類的構造構函數前。
          第二步,在構造函數內調用defineClass()方法,傳給它類名及被Clary稱為原型函數的指針,該函數用于初始化對象的所有屬性和方法。

          _classes.registerClass("ClassA");
          function ClassA(color){
             _classes.defineClass("ClassA",prototypeFunction);

             function prototypeFunction(){
                //...
             }
          }
          第三步,為該類創建init()方法。該方法負責設置該類的所有屬性,它必須接受與構造函數相同的參數。作為一種規約,init()方法總是在defineClass()方法后調用。
          _classes.registerClass("ClassA");
          function ClassA(color){
             _classes.defineClass("ClassA",prototypeFunction);
             this.init(sColor);
             function prototypeFunction(){
               ClassA.prototype.init = function(sColor){
                   this.parentMethod("init");
                   this.color = sColor;
                }
             }
          }
          第四步,在原型函數內添加其他類的方法。
          _classes.registerClass("ClassA");
          function ClassA(color){
             _classes.defineClass("ClassA",prototypeFunction);
             this.init(sColor);
             function prototypeFunction(){
               ClassA.prototype.init = function(sColor){
                   this.parentMethod("init");
                   this.color = sColor;
                }
                ClassA.prototype.sayColor = function(){
                   alert(this.color);
                }
             }
          }
          然后,即可以以常規方式創建ClassA的實例
          var objA = new ClassA("red");
          objA.sayColor();      //outputs "res"

          FeedBack:
          # re: javascript學習筆記(二)--繼承
          2007-04-17 12:57 | cresposhi
          我還是喜歡用混合方式。。。
          up
          不過一直沒搞明白當年call和apply沒出來之前的那種冒充方式是怎么實現的,也就是文中最開始講的那種方法,高人可以指點一下!  回復  更多評論
            
          # re: javascript學習筆記(二)--繼承
          2007-04-17 12:58 | cresposhi
          順便加一句,現在用于實現集成的lib實在太多了,選擇一種lib之后就用它的吧,方便!
            回復  更多評論
            
          # re: javascript學習筆記(二)--繼承
          2007-04-17 15:44 | 小祝
          呵呵~我也不是很清楚呢,看的不是很懂。
          是啊,現在有很多庫很好用啊,這里介紹它的原理嘛。
          有助于理解別人是怎么實現的。  回復  更多評論
            
          # re: javascript學習筆記(二)--繼承
          2008-04-16 00:05 | Aragorn

          老祝的文章太好了!
          呵呵!我也覺得混合方式好些!
          更加有面向對象的感覺!
          對象冒充的方式感覺很復雜,用混合方式既簡潔又很好理解!
          現在的庫包很多,都讓人應接不暇,覺得prototype好些,更像是javascript原型的擴展!
          呵呵!  回復  更多評論
            
          主站蜘蛛池模板: 都江堰市| 新干县| 阿瓦提县| 邵阳县| 凤城市| 华宁县| 察雅县| 乌兰察布市| 佛学| 太仓市| 全南县| 盐边县| 新源县| 登封市| 广丰县| 庆元县| 萝北县| 东阳市| 正蓝旗| 贵南县| 罗甸县| 古蔺县| 余姚市| 左权县| 米易县| 靖江市| 高尔夫| 株洲县| 四平市| 盐亭县| 新绛县| 德保县| 开原市| 云南省| 赤城县| 苏州市| 湘潭县| 关岭| 晋中市| 佳木斯市| 渝北区|