官术网_书友最值得收藏!

1.1 動態類型語言和鴨子類型

編程語言按照數據類型大體可以分為兩類,一類是靜態類型語言,另一類是動態類型語言

靜態類型語言在編譯時便已確定變量的類型,而動態類型語言的變量類型要到程序運行的時候,待變量被賦予某個值之后,才會具有某種類型。

靜態類型語言的優點首先是在編譯時就能發現類型不匹配的錯誤,編輯器可以幫助我們提前避免程序在運行期間有可能發生的一些錯誤。其次,如果在程序中明確地規定了數據類型,編譯器還可以針對這些信息對程序進行一些優化工作,提高程序執行速度。

靜態類型語言的缺點首先是迫使程序員依照強契約來編寫程序,為每個變量規定數據類型,歸根結底只是輔助我們編寫可靠性高程序的一種手段,而不是編寫程序的目的,畢竟大部分人編寫程序的目的是為了完成需求交付生產。其次,類型的聲明也會增加更多的代碼,在程序編寫過程中,這些細節會讓程序員的精力從思考業務邏輯上分散開來。

動態類型語言的優點是編寫的代碼數量更少,看起來也更加簡潔,程序員可以把精力更多地放在業務邏輯上面。雖然不區分類型在某些情況下會讓程序變得難以理解,但整體而言,代碼量越少,越專注于邏輯表達,對閱讀程序是越有幫助的。

動態類型語言的缺點是無法保證變量的類型,從而在程序的運行期有可能發生跟類型相關的錯誤。這好像在商店買了一包牛肉辣條,但是要真正吃到嘴里才知道是不是牛肉味。

在JavaScript中,當我們對一個變量賦值時,顯然不需要考慮它的類型,因此,JavaScript是一門典型的動態類型語言。

動態類型語言對變量類型的寬容給實際編碼帶來了很大的靈活性。由于無需進行類型檢測,我們可以嘗試調用任何對象的任意方法,而無需去考慮它原本是否被設計為擁有該方法。

這一切都建立在鴨子類型(duck typing)的概念上,鴨子類型的通俗說法是:“如果它走起路來像鴨子叫起來也是鴨子那么它就是鴨子。

我們可以通過一個小故事來更深刻地了解鴨子類型。

從前在JavaScript王國里,有一個國王,他覺得世界上最美妙的聲音就是鴨子的叫聲,于是國王召集大臣,要組建一個1000只鴨子組成的合唱團。大臣們找遍了全國,終于找到999只鴨子,但是始終還差一只,最后大臣發現有一只非常特別的雞,它的叫聲跟鴨子一模一樣,于是這只雞就成為了合唱團的最后一員。

這個故事告訴我們,國王要聽的只是鴨子的叫聲,這個聲音的主人到底是雞還是鴨并不重要。鴨子類型指導我們只關注對象的行為,而不關注對象本身,也就是關注HAS-A,而不是IS-A。

下面我們用代碼來模擬這個故事。

        var duck = {
            duckSinging: function(){
              console.log( ’嘎嘎嘎’ );
        };
            }

        var chicken = {
            duckSinging: function(){
              console.log( ’嘎嘎嘎’ );
            }
        };

        var choir = [];    //合唱團

        var joinChoir = function( animal ){
            if ( animal && typeof animal.duckSinging === 'function' ){
                choir.push( animal );
                console.log( ’恭喜加入合唱團’ );
                console.log( ’合唱團已有成員數量:' + choir.length );
            }
        };

        joinChoir( duck );    //恭喜加入合唱團
        joinChoir( chicken );    //恭喜加入合唱團

我們看到,對于加入合唱團的動物,大臣們根本無需檢查它們的類型,而是只需要保證它們擁有duckSinging方法。如果下次期望加入合唱團的是一只小狗,而這只小狗剛好也會鴨子叫,我相信這只小狗也能順利加入。

在動態類型語言的面向對象設計中,鴨子類型的概念至關重要。利用鴨子類型的思想,我們不必借助超類型的幫助,就能輕松地在動態類型語言中實現一個原則:“面向接口編程,而不是面向實現編程”。例如,一個對象若有push和pop方法,并且這些方法提供了正確的實現,它就可以被當作棧來使用。一個對象如果有length屬性,也可以依照下標來存取屬性(最好還要擁有slice和splice等方法),這個對象就可以被當作數組來使用。

在靜態類型語言中,要實現“面向接口編程”并不是一件容易的事情,往往要通過抽象類或者接口等將對象進行向上轉型。當對象的真正類型被隱藏在它的超類型身后,這些對象才能在類型檢查系統的“監視”之下互相被替換使用。只有當對象能夠被互相替換使用,才能體現出對象多態性的價值。

“面向接口編程”是設計模式中最重要的思想,但在JavaScript語言中,“面向接口編程”的過程跟主流的靜態類型語言不一樣,因此,在JavaScript中實現設計模式的過程與在一些我們熟悉的語言中實現的過程會大相徑庭。

主站蜘蛛池模板: 英德市| 利津县| 祁门县| 南宁市| 丹棱县| 永丰县| 攀枝花市| 永顺县| 石屏县| 慈利县| 石河子市| 鹤峰县| 黔南| 虹口区| 新邵县| 曲水县| 手机| 中西区| 隆子县| 清丰县| 泸水县| 婺源县| 湘乡市| 老河口市| 五大连池市| 邵武市| 南和县| 三门峡市| 含山县| 米易县| 襄汾县| 林甸县| 永平县| 兴义市| 壶关县| 呈贡县| 湟中县| 贺州市| 乌拉特后旗| 贵定县| 习水县|