<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 154  文章 - 60  trackbacks - 0
    <2007年10月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    聲明:

    該blog是為了收集資料,認(rèn)識(shí)朋友,學(xué)習(xí)、提高技術(shù),所以本blog的內(nèi)容除非聲明,否則一律為轉(zhuǎn)載!!

    感謝那些公開自己技術(shù)成果的高人們!!!

    支持開源,尊重他人的勞動(dòng)!!

    常用鏈接

    留言簿(3)

    隨筆分類(148)

    隨筆檔案(143)

    收藏夾(2)

    其他

    學(xué)習(xí)(技術(shù))

    觀察思考(非技術(shù))

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    利用共享prototype實(shí)現(xiàn)繼承
    繼承是面向?qū)ο箝_發(fā)的又一個(gè)重要概念,它可以將現(xiàn)實(shí)生活的概念對(duì)應(yīng)到程序邏輯中。例如水果是一個(gè)類,具有一些公共的性質(zhì);而蘋果也是一類,但它們屬于水果,所以蘋果應(yīng)該繼承于水果。
    在JavaScript中沒有專門的機(jī)制來實(shí)現(xiàn)類的繼承,但可以通過拷貝一個(gè)類的prototype到另外一個(gè)類來實(shí)現(xiàn)繼承。一種簡(jiǎn)單的實(shí)現(xiàn)如下:
    fucntion class1(){
          //構(gòu)造函數(shù)
    }

    function class2(){
          //構(gòu)造函數(shù)
    }
    class2.prototype=class1.prototype;
    class2.prototype.moreProperty1="xxx";
    class2.prototype.moreMethod1=function(){
          //方法實(shí)現(xiàn)代碼
    }
    var obj=new class2();
    這樣,首先是class2具有了和class1一樣的prototype,不考慮構(gòu)造函數(shù),兩個(gè)類是等價(jià)的。隨后,又通過prototype給class2賦予了兩個(gè)額外的方法。所以class2是在class1的基礎(chǔ)上增加了屬性和方法,這就實(shí)現(xiàn)了類的繼承。
    JavaScript提供了instanceof操作符來判斷一個(gè)對(duì)象是否是某個(gè)類的實(shí)例,對(duì)于上面創(chuàng)建的obj對(duì)象,下面兩條語句都是成立的:
    obj instanceof class1
    obj instanceof class2
    表面上看,上面的實(shí)現(xiàn)完全可行,JavaScript也能夠正確的理解這種繼承關(guān)系,obj同時(shí)是class1和class2的實(shí)例。事是上不對(duì),JavaScript的這種理解實(shí)際上是基于一種很簡(jiǎn)單的策略。看下面的代碼,先使用prototype讓class2繼承于class1,再在class2中重復(fù)定義method方法:
    <script language="JavaScript" type="text/javascript">
    <!--
    //定義class1
    function class1(){
          //構(gòu)造函數(shù)
    }
    //定義class1的成員
    class1.prototype={
          m1:function(){
                alert(1);
          }
    }
    //定義class2
    function class2(){
          //構(gòu)造函數(shù)
    }
    //讓class2繼承于class1
    class2.prototype=class1.prototype;
    //給class2重復(fù)定義方法method
    class2.prototype.method=function(){
          alert(2);
    }
    //創(chuàng)建兩個(gè)類的實(shí)例
    var obj1=new class1();
    var obj2=new class2();
    //分別調(diào)用兩個(gè)對(duì)象的method方法
    obj1.method();
    obj2.method();
    //-->
    </script>
    從代碼執(zhí)行結(jié)果看,彈出了兩次對(duì)話框“2”。由此可見,當(dāng)對(duì)class2進(jìn)行prototype的改變時(shí),class1的prototype也隨之改變,即使對(duì)class2的prototype增減一些成員,class1的成員也隨之改變。所以class1和class2僅僅是構(gòu)造函數(shù)不同的兩個(gè)類,它們保持著相同的成員定義。從這里,相信讀者已經(jīng)發(fā)現(xiàn)了其中的奧妙:class1和class2的prototype是完全相同的,是對(duì)同一個(gè)對(duì)象的引用。其實(shí)從這條賦值語句就可以看出來:
    //讓class2繼承于class1
    class2.prototype=class1.prototype;
    在JavaScript中,除了基本的數(shù)據(jù)類型(數(shù)字、字符串、布爾等),所有的賦值以及函數(shù)參數(shù)都是引用傳遞,而不是值傳遞。所以上面的語句僅僅是讓class2的prototype對(duì)象引用class1的prototype,造成了類成員定義始終保持一致的效果。從這里也看到了instanceof操作符的執(zhí)行機(jī)制,它就是判斷一個(gè)對(duì)象是否是一個(gè)prototype的實(shí)例,因?yàn)檫@里的obj1和obj2都是對(duì)應(yīng)于同一個(gè)prototype,所以它們instanceof的結(jié)果都是相同的。
    因此,使用prototype引用拷貝實(shí)現(xiàn)繼承不是一種正確的辦法。但在要求不嚴(yán)格的情況下,卻也是一種合理的方法,惟一的約束是不允許類成員的覆蓋定義。下面一節(jié),將利用反射機(jī)制和prototype來實(shí)現(xiàn)正確的類繼承。
    利用反射機(jī)制和prototype實(shí)現(xiàn)繼承
    前面一節(jié)介紹的共享prototype來實(shí)現(xiàn)類的繼承,不是一種很好的方法,畢竟兩個(gè)類是共享的一個(gè)prototype,任何對(duì)成員的重定義都會(huì)互相影響,不是嚴(yán)格意義的繼承。但在這個(gè)思想的基礎(chǔ)上,可以利用反射機(jī)制來實(shí)現(xiàn)類的繼承,思路如下:利用for(…in…)語句枚舉出所有基類prototype的成員,并將其賦值給子類的prototype對(duì)象。例如:
    <script language="JavaScript" type="text/javascript">
    <!--
    function class1(){
          //構(gòu)造函數(shù)
    }
    class1.prototype={
          method:function(){
               alert(1);
          },
          method2:function(){
               alert("method2");
          }
    }
    function class2(){
          //構(gòu)造函數(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)建兩個(gè)類的實(shí)例
    var obj1=new class1();
    var obj2=new class2();
    //分別調(diào)用obj1和obj2的method方法
    obj1.method();
    obj2.method();
    //分別調(diào)用obj1和obj2的method2方法
    obj1.method2();
    obj2.method2();
    //-->
    </script>
    從運(yùn)行結(jié)果可見,obj2中重復(fù)定義的method已經(jīng)覆蓋了繼承的method方法,同時(shí)method2方法未受影響。而且obj1中的method方法仍然保持了原有的定義。這樣,就實(shí)現(xiàn)了正確意義的類的繼承。為了方便開發(fā),可以為每個(gè)類添加一個(gè)共有的方法,用以實(shí)現(xiàn)類的繼承:
    //為類添加靜態(tài)方法inherit表示繼承于某類
    Function.prototype.inherit=function(baseClass){
         for(var p in baseClass.prototype){
                this.prototype[p]=baseClass.prototype[p];
         }
    }
    這里使用所有函數(shù)對(duì)象(類)的共同類Function來添加繼承方法,這樣所有的類都會(huì)有一個(gè)inherit方法,用以實(shí)現(xiàn)繼承,讀者可以仔細(xì)理解這種用法。于是,上面代碼中的:
    //讓class2繼承于class1
    for(var p in class1.prototype){
           class2.prototype[p]=class1.prototype[p];
    }
    可以改寫為:
    //讓class2繼承于class1
    class2.inherit(class1)
    這樣代碼邏輯變的更加清楚,也更容易理解。通過這種方法實(shí)現(xiàn)的繼承,有一個(gè)缺點(diǎn),就是在class2中添加類成員定義時(shí),不能給prototype直接賦值,而只能對(duì)其屬性進(jìn)行賦值,例如不能寫為:
    class2.prototype={
          //成員定義
    }
    而只能寫為:
    class2.prototype.propertyName=someValue;
    class2.prototype.methodName=function(){
          //語句
    }
    由此可見,這樣實(shí)現(xiàn)繼承仍然要以犧牲一定的代碼可讀性為代價(jià),在下一節(jié)將介紹prototype-1.3.1框架(注:prototype-1.3.1框架是一個(gè)JavaScript類庫,擴(kuò)展了基本對(duì)象功能,并提供了實(shí)用工具詳見附錄。)中實(shí)現(xiàn)的類的繼承機(jī)制,不僅基類可以用對(duì)象直接賦值給property,而且在派生類中也可以同樣實(shí)現(xiàn),使代碼邏輯更加清晰,也更能體現(xiàn)面向?qū)ο蟮恼Z言特點(diǎn)。

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

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

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

    posted on 2007-10-09 09:42 lk 閱讀(5729) 評(píng)論(3)  編輯  收藏 所屬分類: ajax&js

    FeedBack:
    # re: JavaScript類的繼承 2007-12-12 00:13 Mic
    不明白執(zhí)行的時(shí)機(jī)  請(qǐng)大蝦幫忙啊
    <script language="javascript" type="text/javascript">
    //定義extend方法
    Object.extend=function(destination,source){
    for(var property in source)
    {

    destination[property]=source[property];
    }

    return destination;
    }

    //通過Object類為每個(gè)對(duì)象添加extend方法
    Object.prototype.extend=function(object){
    return Object.extend.apply(this,[this,object]);
    }

    function class1()
    {

    }

    class1.prototype={
    method:function(){
    alert("class1");
    },
    method2:function(){
    alert("method2");
    }
    }

    function class2(){

    }

    class2.prototype=(new class1()).extend({
    name:"Michael",
    method:function(){
    alert("class2");
    }
    });

    var obj1=new class1();
    var obj2=new class2();

    //實(shí)驗(yàn)obj1和obj2的方法
    obj1.method();
    obj2.method();

    obj1.method2();
    obj2.method2();
    </script>  回復(fù)  更多評(píng)論
      
    # re: JavaScript類的繼承[未登錄] 2007-12-29 19:43 cy
    第一種方法直接用class2.prototype=new class1();不就避免對(duì)class2的prototype進(jìn)行引用操作了么?
    <script language="JavaScript" type="text/javascript">
    <!--
    //定義class1
    function class1(){
    //構(gòu)造函數(shù)
    }
    //定義class1的成員
    class1.prototype={
    m1:function(){
    alert(1);
    }
    }
    //定義class2
    function class2(){
    //構(gòu)造函數(shù)
    }
    //讓class2繼承于class1
    class2.prototype=new class1();
    //給class2重復(fù)定義方法method
    class2.prototype.method=function(){
    alert(2);
    }
    //創(chuàng)建兩個(gè)類的實(shí)例
    var obj1=new class1();
    var obj2=new class2();
    //分別調(diào)用兩個(gè)對(duì)象的method方法
    obj1.method();
    obj2.method();
    //-->
    </script>
      回復(fù)  更多評(píng)論
      
    # re: JavaScript類的繼承 2013-10-03 08:07 LinuxTimes
    一種符合C++、Java、Python 等語言習(xí)慣的 JavaScript 語言的類繼承實(shí)現(xiàn)方式:
    http://www.linuxtimes.cn/2013/10/02/class-inheritance-javascript/

    請(qǐng)指教!  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 一级毛片免费观看不收费| 久久久久久一品道精品免费看 | 免费国产精品视频| 一级做a爱过程免费视频高清| 亚洲国产高清视频| 国产极品美女高潮抽搐免费网站| v片免费在线观看| 亚洲最大在线观看| 亚洲精品无码99在线观看| 最近2019免费中文字幕6| 高潮内射免费看片| 亚洲成AV人综合在线观看| 亚洲av无码成人精品区在线播放 | 永久免费av无码不卡在线观看 | 最近中文字幕mv免费高清视频7 | 亚洲AV综合永久无码精品天堂| 国产亚洲一区二区三区在线不卡| 国产人成免费视频网站| 国产免费牲交视频免费播放| 亚洲国产激情在线一区| 亚洲成AV人片在线观看无码 | 久久精品成人免费国产片小草| 亚洲乱码一二三四区国产| 在线播放亚洲第一字幕| 免费看香港一级毛片| 51在线视频免费观看视频| 一个人看的www免费高清| 亚洲男人的天堂网站| 亚洲精品高清国产麻豆专区| 国产亚洲美女精品久久久2020| 在线免费观看韩国a视频| 四虎在线成人免费网站| 免费在线观看一级片| 人碰人碰人成人免费视频| 亚洲AV无码一区二区三区牲色| 亚洲女人初试黑人巨高清| 亚洲av激情无码专区在线播放| 亚洲精品成人久久久| 俄罗斯极品美女毛片免费播放| 毛片免费在线观看网站| 国内精自视频品线六区免费 |