道非道 非常道

          勤思、謹言、慎行、厚積、薄發

          統計

          web

          天圓

          經濟 政治 軍事

          鍵康

          [轉] javascript的prototype繼承

            轉自:http://www.cnblogs.com/goody9807/archive/2007/04/16/715109.html
           
          基本的用法 把ClassA的一個實例賦值給ClassB ClassB就繼承了ClassA的所有屬性

          <script>
          function ClassA()
          {
              
          this.a='a';
          }

          function ClassB()
          {
              
          this.b='b';
          }

          ClassB.prototype
          =new ClassA();
          var objB=new ClassB();
          for(var p in objB)document.write(p+"<br>");
          </script>


          從原型繼承理論的角度去考慮 js的原型繼承是引用原型 不是復制原型
          所以 修改原型會導致所有B的實例的變化

          <script>
          function ClassA()
          {
              
          this.a='a';
          }

          function ClassB()
          {
              
          this.b='b';
          }

          ClassB.prototype
          =new ClassA();
          var objB=new ClassB();
          alert(objB.a);
          ClassB.prototype.a
          ='changed!!';
          alert(objB.a);
          </script>


          然而 子類對象的寫操作只訪問子類對象中成員 它們之間不會互相影響
          因此 寫是寫子類 讀是讀原型(如果子類中沒有的話)

          <script>
          function ClassA()
          {
              
          this.a='a';
          }

          function ClassB()
          {
              
          this.b='b';
          }

          ClassB.prototype
          =new ClassA();
          var objB1=new ClassB();
          var objB2=new ClassB();
          objB1.a
          ='!!!';
          alert(objB1.a);
          alert(objB2.a);
          </script>


          每個子類對象都執有同一個原型的引用 所以子類對象中的原型成員實際是同一個

          <script>
          function ClassA()
          {
              
          this.a=function(){alert();};
          }

          function ClassB()
          {
              
          this.b=function(){alert();};
          }

          ClassB.prototype
          =new ClassA();
          var objB1=new ClassB();
          var objB2=new ClassB();
          alert(objB1.a
          ==objB2.a);
          alert(objB1.b
          ==objB2.b);
          </script>



          構造子類時 原型的構造函數不會被執行
          <script>
          function ClassA()
          {
              alert(
          "a");
              
          this.a=function(){alert();};
          }

          function ClassB()
          {
              alert(
          "b");
              
          this.b=function(){alert();};
          }

          ClassB.prototype
          =new ClassA();
          var objB1=new ClassB();
          var objB2=new ClassB();
          </script>


          接下來是致命的,在子類對象中訪問原型的成員對象:
          <script>
          function ClassA()
          {
              
          this.a=[];
          }

          function ClassB()
          {
              
          this.b=function(){alert();};
          }

          ClassB.prototype
          =new ClassA();
          var objB1=new ClassB();
          var objB2=new ClassB();
          objB1.a.push(
          1,2,3);
          alert(objB2.a);
          //所有b的實例中的a成員全都變了!!
          </script>


          所以 在prototype繼承中 原型類中不能有成員對象! 所有成員必須是值類型數據(string也可以)

          用prototype繼承有執行效率高,不會浪費內存,為父類動態添置方法后子類中馬上可見等的優點。

          我就非常喜歡用prototype繼承。

          prototype繼承是通過把子類的原型對象(prototype)設置成父類的一個實例來進行繼承的。

          只簡單的這樣設置繼承的確如樓主所說,有不少缺點。總的來說有四個缺點:

          缺點一:父類的構造函數不是像JAVA中那樣在給子類進行實例化時執行的,而是在設置繼承的時候執行的,并且只執行一次。這往往不是我們希望的,特別是父類的構造函數中有一些特殊操作的情況下。

          缺點二:由于父類的構造函數不是在子類進行實例化時執行,在父類的構造函數中設置的成員變量到了子類中就成了所有實例對象公有的公共變量。由于 JavaScript中繼承只發生在“獲取”屬性的值時,對于屬性的值是String,Number和Boolean這些數據本身不能被修改的類型時沒有 什么影響。但是Array和Object類型就會有問題。
          缺點三:如果父類的構造函數需要參數,我們就沒有辦法了。

          缺點四:子類原本的原型對象被替換了,子類本身的constructor屬性就沒有了。在類的實例取它的constructor屬性時,取得的是從父類中繼承的constructor屬性,從而constructor的值是父類而不是子類。


          我也曾經為了這四個缺點頭疼過,于是對prototype繼承進行改造。
          我試了幾種方法,下面是我覺得最好的一種。我把它寫成Function對象的一個方法,這樣用的時候方便。方法如下:
          //類的繼承-海浪版
          Function.prototype.Extends = function (parentClass)
          {
            
          var Bs = new Function();
            Bs.prototype 
          = parentClass.prototype;
            
          this.prototype = new Bs();
            
          this.prototype.Super = parentClass;
            
          this.prototype.constructor = this;
          }

          posted on 2009-07-08 14:04 星期五 閱讀(183) 評論(0)  編輯  收藏 所屬分類: web 開發

          主站蜘蛛池模板: 葫芦岛市| 神池县| 鞍山市| 上思县| 宣恩县| 巴东县| 星子县| 铜山县| 惠水县| 扬中市| 读书| 赣州市| 苗栗市| 泗水县| 涿州市| 蓬安县| 陵川县| 成都市| 阿巴嘎旗| 宕昌县| 山阴县| 罗源县| 永修县| 新泰市| 福清市| 谢通门县| 黄陵县| 台东县| 德江县| 南岸区| 阳谷县| 大方县| 微山县| 平邑县| 巴彦淖尔市| 长兴县| 施秉县| 桐乡市| 黄平县| 托克逊县| 汕头市|