- JavaScript設計模式與開發實踐
- 曾探
- 1602字
- 2020-01-10 15:38:12
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中實現設計模式的過程與在一些我們熟悉的語言中實現的過程會大相徑庭。
- Functional Python Programming
- GraphQL學習指南
- Linux核心技術從小白到大牛
- Software Testing using Visual Studio 2012
- Python進階編程:編寫更高效、優雅的Python代碼
- Visual C++應用開發
- Oracle從入門到精通(第5版)
- 低代碼平臺開發實踐:基于React
- ASP.NET開發與應用教程
- OpenCV with Python Blueprints
- 愛上C語言:C KISS
- Java RESTful Web Service實戰
- Java程序設計及應用開發
- 軟技能2:軟件開發者職業生涯指南
- Leaflet.js Essentials