曾經對Javascript的面向對象相關知識也有過了解,從各類博客、書籍上也學到了不少。可是最近在看《Javascript設計模式與開發實戰》這本書時發現該書對這方面的知識點介紹的很易於理解,所以總結出該文章分享給你們,同時也做爲本身往後複習的筆記。編程
編程語言按照數據類型大致可分爲靜態類型語言和動態類型語言。
靜態類型語言就是指在編譯時就已經肯定了變量的類型,好比C++在聲明變量時的int關鍵字。
動態類型語言的變量類型要在程序運行時被賦值後才能肯定。
在Javascript中,咱們在對一個變量賦值時,顯然不須要考慮它的類型。所以,Javascript是一門經典的動態類型語言。設計模式
動態類型語言在實際編碼時帶來了很大的靈活性,咱們能夠嘗試調用任意對象的任意方法,而不須要考慮它本來是否被設計擁有該方法。
這些都創建在鴨子類型的概念上,通俗的說法是「若是它走起路來像鴨子,叫起來也是鴨子,那麼它就是鴨子。」
好吧我知道你可能不太理解,咱們能夠經過一個故事來深刻理解:數組
從前在Javascript王國裏,有一個國王,他以爲世界上最美妙的聲音就是鴨子的叫聲,因而國王召集大臣,要組建一個100只鴨子組成的合唱團。可是大臣們找遍了全國,只找到了999只鴨子,最後大臣發現有一隻很是特別的雞,它的叫聲跟鴨子如出一轍,因而這隻雞就成爲了合唱團的最後一員。
這個故事說明,國王只是想要鴨子的叫聲,但它的主人是雞仍是鴨都不重要。咱們只關注對象的行爲,而不關注對象自己。
經過代碼你可能能更好的的理解:編程語言
let duck = { duckSay: function () { console.log('ga') } } let chicken = { duckSay: function () { console.log('ga') } } // 合唱團 let choir = [] let joinChoir = function (animal) { if (animal && typeof animal.duckSay === 'function') { choir.push(animal) console.log('加入合唱團成功') } } joinChoir(duck) // 加入合唱團成功 joinChoir(chicken) // 加入合唱團成功
咱們發現,只要動物擁有duckSay
方法,它就能夠加入合唱團,而並不關心它究竟是誰。
鴨子類型的概念相當重要,好比一個對象有了length
屬性,也能夠依照下標來存取屬性,這個對象就能夠被當作數組來使用。(這裏能夠思考咱們在處理函數傳入的參數arguments
時的一些操做)函數
多態是指同一操做做用於不一樣的對象上面,能夠產生不一樣的解釋和不一樣的執行結果。也就是給不一樣對象發送同一消息,會有不一樣的反饋。
這裏咱們依舊經過一個故事來說解:google
主人家裏養了兩隻動物,一隻雞和一隻鴨,當主人發出叫的命令時,鴨會gagaga的叫,而雞會gegege的叫。
上面的故事用代碼實現就是:編碼
let makeSound = function (animal) { if (animal instanceof Duck) { console.log('ga') } else if (animal instanceof Chicken) { console.log('ge') } } let Duck = function () {} let Chicken = function () {} makeSound(new Duck()) // ga makeSound(new Chicken()) // ge
多態背後的思想是將「作什麼」和「誰去作以及怎樣去作」分離開,即將「不變的事情」和「可變的事情」分離開。這樣的程序是可生長的,也是符合開放-封閉原則。
所以咱們能夠將不變的部分隔離出來,也就是全部的動物都會叫prototype
let makeSound = function (animal) { animal.sound() }
而後把可變的部分封裝起來:設計
let Duck = function () {} Duck.prototype.sound = function () { console.log('ga') } let Chicken = function () {} Chicken.prototype.sound = function () { console.log('ge') } makeSound(new Duck()) // ga makeSound(new Chicken()) // ge
再好比咱們要開發一個地圖應用,如今有百度和谷歌兩家地圖提供了API,且均提供了show()
方法,代碼以下:code
let googleMap = { show: function () { console.log('開始渲染谷歌地圖') } } let baiduMap = { show: function () { console.log('開始渲染百度地圖') } } let renderMap = function (type) { if (type === 'google') { googleMap.show() } else if (type === 'baidu') { baiduMap.show() } } renderMap('google') // 開始渲染谷歌地圖 renderMap('baidu') // 開始渲染百度地圖
能夠看到,雖然renderMap()
函數保持了必定的彈性,可是這種彈性很脆弱,若是再換另外一個地圖,有須要修改renderMap函數,繼續添加條件分支語句。
咱們能夠把程序相同的部分抽象出來,即顯示某個地圖:
let renderMap = function (map) { if (map.show instanceof Function) { map.show() } }
但願能爲你帶來一些啓發。
參考資料: 《JavaScript 設計模式與開發實戰》 第一章