亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Javascript繼承(下)——干嘛要繼承

系統(tǒng) 2973 0

?

Javascript繼承(上)——對象構建

?

Quiz1

?

Javascript真的需要類(Class)么?

我們首先先看下其他有類(Class)的面向?qū)ο笳Z言(如:Java)的一些特性。

?

父類與子類 ?

父類(Superclass)和子類(Subclass),并不是為了解決父親與兒子的問題,而是為了解決類的包含關系的,我們用S ub 表示“子類”,用S up 表示“父類”,則有:

S ub ? S up

這是有區(qū)別的,例如通常我們能夠?qū)⒆宇惍敵筛割悂硎褂?,但認人的時候我們并不能把兒子當成父親。

或者可以這么說,父類和子類不是為了解決類間存在相同方法或者屬性的。

?

舉個例子

有人喜歡這樣做:

我們需要一些動物的類,以便在屏幕上創(chuàng)建一些移動的動物,但移動的動物有些在空中飛行,有些在路上行走。

所以創(chuàng)建兩個父類,一個是Fly,一個是Walk:

        
          Class Fly{
    fly(){}
}

Class Walk{
    walk(){}
}
        
      

然后獅子們(還可以再建些其他的在路上行走的動物)就屬于Walk類,老鷹們(也還可以再建些其他在天上飛行的動物)就屬于Fly類:

        
          Class Lion extend Walk{
        
        
          }

Class Eagle extend Fly{
        
        
}
      

最后對Lion和Eagle類創(chuàng)建一些實例,調(diào)用相應的方法,屏幕上就會有一些獅子和老鷹在移動了。

但這可能并不是一個好的設計,比如明天老板突然一拍大腦,他要有一種叫天馬( Pegasus )的動物,它們即會在天上飛,又會在路上走,時而要飛行,時候要行走。

在這種情況下,這個方案就全然無用了。

?

為什么這個設計失敗了?

繼承是有條件的,子類必須能嚴格的向上轉(zhuǎn)型(變成父類)。

在上面這個例子中:

  • 獅子(Lion)被假設等同于行走動物(Walk),老鷹(Eagle)被假設等同于飛行動物(Fly)。
  • 這看起來很成功,因為子類能嚴格向上轉(zhuǎn)型,但他有隱患。
  • 當有一種天馬(Pegasus)介入到里面的時候,我們才發(fā)現(xiàn)獅子其實只是“會行走的動物”,老鷹其實只是“會飛行的動物”,這不意味著動物一輩子只能飛行或者行走,所以即會飛行又會行走的天馬就找不到自己的歸屬了。

這個例子很好的證明了,子類和父類不是為了解決類間具有相同的方法的:

一些動物都會行走,需要擁有行走(Walk)這個方法,但這不應該由子類和父類實現(xiàn)。

?

組合

我們可以這樣解決這個問題:

      
        Class Lion{
    walker 
      
      = 
      
        new
      
      
         Walk();
    walk(){
        
      
      
        return
      
      
         walker.walk();
    }
}

Class Eagle{
    flyer 
      
      = 
      
        new
      
      
         Fly();
    fly(){
        
      
      
        return
      
      
         flyer.fly();
    }
}

Class Pegasus{
    walker 
      
      = 
      
        new
      
      
         Walk();
    flyer 
      
      = 
      
        new
      
      
         Fly();
    walk(){
        
      
      
        return
      
      
         walker.walk();
    }
    fly(){
        
      
      
        return
      
      
         flyer.fly();
    }
}
      
    

組合是簡單的在新類內(nèi)部創(chuàng)建原有類對象。所以組合才是為了解決類間具有相同的方法的。在這個例子里面:

Walk被當成“會行走的動物應該擁有的方法集合”,同理Fly被當成“會行走的動物應該擁有的方法集合”,所以對于天馬(Pegasus),我們只需要對Walk和Fly進行組合就行了。

?

繼承的目的

繼承并非代碼復用的唯一方法,但繼承有他的優(yōu)勢:

子類可以向上轉(zhuǎn)型變成父類。

這樣我們就可以忽略所有的子類差異,當成相同的類來操作,例如:

我們有方法fn(A),fn(B),這兩個方法實際是相似的,我們想復用他們。

則我們可以通過設立一個父類C,其中A是C的子類,B是C的子類,那么fn(C)就可以復用在A和B身上了。

?

回到Javascript

但回到Javascript,我們發(fā)現(xiàn)上面的例子是不成立的。

因為Javascript本身是弱類型語言,它并不會在操作前(因為他不用編譯)關注自己操作的對象類型是什么。他只會執(zhí)行成功,或者發(fā)生錯誤。

這時候,繼承顯得并不必要了。那么類也就同樣不是必要的了。

I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function. The super idea is fairly important in the classical pattern, but it appears to be unnecessary in the prototypal and functional patterns. I now see my early attempts to support the classical model in JavaScript as a mistake.

—— Douglas Crockford

我寫Javascript代碼已經(jīng)8年了,但我從來沒有發(fā)現(xiàn)需要使用超類函數(shù)。超類的想法在古典設計模式是非常重要的,但這在以原型和函數(shù)為基調(diào)的模式中并不必要。我現(xiàn)在覺得,早期我試圖讓Javascript支持經(jīng)典模式是一個錯誤的決定。

?

安全環(huán)境

當然,你可以手動去判斷類型,控制參數(shù)的類型,進而提供一個較為安全的環(huán)境。

例如同樣作為弱類型腳本語言的PHP,為了模擬強類型面向?qū)ο笳Z言設置安全環(huán)境,不得不這么做:

        
          class
        
        
           ShopProductWriter{
    
        
        
          public
        
        
           function write( $shopProduct ){
        
        
        
          if
        
        ( ! ( $shopProduct 
        
          instanceof
        
         CdProduct ) && ! ( $shopProduct 
        
          instanceof
        
        
           BookProduct ) ){
            die( 
        
        "輸入錯誤的類型"
        
           );
        }
        
        
        
          //
        
        
          如果類型正確就執(zhí)行一些代碼
        
        
              }
}
        
      

——PHP Objects, Patterns, and Practtice Third Edition . Matt Zandstra

但這只是一個非常丑陋的方案而已。

?

經(jīng)典繼承語法糖實現(xiàn)

不過經(jīng)典繼承依然是許多人喜歡的方式。所以YUI、Prototype、Dojo、MooTools都提供了自己的實現(xiàn)方案。

其中較為常見的方案中,語法大概是這樣的:

      
        var
      
       Person =
      
         Class.extend({
  init: 
      
      
        function
      
      
        (isDancing){
    
      
      
        this
      
      .dancing =
      
         isDancing;
  }
});

      
      
        var
      
       Dancer =
      
         Person.extend({
  init: 
      
      
        function
      
      
        (){
    
      
      
        this
      
      ._super( 
      
        true
      
      
         );
  }
});


      
      
        var
      
       n = 
      
        new
      
      
         Dancer();
alert(n.dancing); 
      
      
        //
      
      
        true
      
    

最重要的實現(xiàn)是對this._super的實現(xiàn),其實extend函數(shù)只是將傳進來的對象重新組裝了一下,變成一個原型對象,新構造函數(shù)的prototype里。

具體實現(xiàn)請查看參考文獻1。

?

ECMAScript 6的經(jīng)典繼承語法糖

對于類庫各自實現(xiàn),導致經(jīng)典繼承語法眾多,ECMA組織貌似不太滿意,他們試圖在ECMAScript 6中加入更加直觀的經(jīng)典繼承語法糖:

      
        class Animal {
    constructor(name) {
        
      
      
        this
      
      .name =
      
         name;
    }

    sayName() {
        console.log(
      
      
        this
      
      
        .name);
    }
}

class Dog extends Animal {
    constructor(name) {
        super(name);
    }

    bark() {
        console.log(
      
      "Woof!"
      
        );
    }
}
      
    

?

總結(jié)

  • 實際上,Javascript中經(jīng)典繼承并不是必要的。
  • 然而基于許多人喜歡經(jīng)典繼承模型,所以在新版的ECMAScript 6中提供了相關語法糖。
  • 不過在中國,前端想廣泛使用該語法糖應該是一個遙遠的故事……

?

Quiz2

那Javascript特有的繼承呢?

?

原型繼承

原型繼承不是解決經(jīng)典繼承中的集合包含關系的,實際上原型繼承是解決從屬關系的,用數(shù)學表達就是:

  S ub. prototype ?∈ ? S up

子級構造函數(shù)(子類型)原型是一個父級構造函數(shù)(父類型)構建的實例對象。原型實際上是子類型實例中需要共享的東西:

      
        function
      
      
         Being(){
    
      
      
        this
      
      .living = 
      
        true
      
      
        ;
}
Being.prototype.walk 
      
      = 
      
        function
      
      
        (){
    alert(
      
      "I' m walking"
      
        );
};


      
      
        function
      
      
         Dancer(){
    
      
      
        this
      
      .dancing = 
      
        true
      
      
        ;
}
Dancer.prototype 
      
      = 
      
        new
      
      
         Being();
Dancer.prototype.dance 
      
      = 
      
        function
      
      
        (){
    alert(
      
      "I'm dancing"
      
        );
};


      
      
        var
      
       one = 
      
        new
      
      
         Dancer();
one.walk();
one.dance();
      
    

利用借用、寄生等技術可以產(chǎn)生很多不同的繼承效果,但這些技術都只是為了解決原型繼承中屬性和方法一些公用與非公用的問題罷了。由于篇幅問題就不展開討論了,有興趣可以參考《Javascript高級程序設計》相關內(nèi)容。

?

思考題?

1.  文章開頭關于天馬(Pegasus)的題目,如果在Javascript上,應該如何設計呢?例如我們有下列兩個類型:

      
        function
      
      
         Walk(){
    
      
      
        this
      
      .walk = 
      
        function
      
      
        (){
        
      
      
        //
      
      
        walk
      
      
            };
}


      
      
        function
      
      
         Fly(){
    
      
      
        this
      
      .fly = 
      
        function
      
      
        (){
        
      
      
        //
      
      
        fly
      
      
            };
}
      
    

?

參考資料

?

Simple JavaScript Inheritance . John Resig?.? March 20th, 2008

JavaScript Inheritance – How And Why ?. Robert Nyman?.? October 6, 2008

JavaScript需要類嗎?? ?.?紫云飛(譯) .? 2012-10-17

Javascript繼承(下)——干嘛要繼承


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美大尺码毛片 | 深夜在线免费 | 日本一级毛片免费 | 综合久久一区二区三区 | 一级特黄aaa大片29 | 欧美又乱又伦观看 | 免费黄a | 亚洲人成高清 | 99精品国产自产在线观看 | 国产精品一区二区三区四区五区 | 日韩精品在线视频观看 | 亚洲a级黄色片 | 全部免费特黄特色大片视频 | 精品视频一区二区三区在线播放 | 国产综合亚洲欧美日韩一区二区 | 性欧美处 | 四虎精品影院在线观看视频 | 91在线视频免费 | 黄色毛片免费观看 | 在线综合色| 久久亚洲高清观看 | 高清在线不卡 | 久久精品久久久久久久久人 | 欧美亚洲中日韩中文字幕在线 | 抱着cao才爽视频 | 孕妇孕妇aaaaa级毛片视频 | 88国产经典欧美一区二区三区 | 一级毛片卡 | 香蕉网站狼人久久五月亭亭 | 天天躁日日躁aaaaxxxx | 亚洲人人精品 | 97影院九七理论片男女高清 | 久久视频精品线视频在线网站 | 日本不卡毛片一二三四 | 日韩欧美毛片免费观看视频 | 日本精品久久久久久久 | 亚洲精品人成在线观看 | 色视频久久 | 91视频国产91久久久 | 天天摸天天草 | 日本黄色网址视频 |