摘要:動態類型語言和鴨子類型編程語言按照數據類型大體可分為靜態類型語言和動態類型語言。鴨子類型的概念至關重要,比如一個對象有了屬性,也可以依照下標來存取屬性,這個對象就可以被當做數組來使用。
前言
曾經對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時的一些操作)
多態是指同一操作作用于不同的對象上面,可以產生不同的解釋和不同的執行結果。也就是給不同對象發送同一消息,會有不同的反饋。
這里我們依舊通過一個故事來講解:
主人家里養了兩只動物,一只雞和一只鴨,當主人發出叫的命令時,鴨會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
多態背后的思想是將“做什么”和“誰去做以及怎樣去做”分離開,即將“不變的事情”和“可變的事情”分離開。這樣的程序是可生長的,也是符合開放-封閉原則。
因此我們可以將不變的部分隔離出來,也就是所有的動物都會叫
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()方法,代碼如下:
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 設計模式與開發實戰》 第一章
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100426.html
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:在中,并沒有對抽象類和接口的支持。例如,當對象需要對象的能力時,可以有選擇地把對象的構造器的原型指向對象,從而達到繼承的效果。本節內容為設計模式與開發實踐第一章筆記。 動態類型語言 編程語言按數據類型大體可以分為兩類:靜態類型語言與動態類型語言。 靜態類型語言在編譯時已確定變量類型,動態類型語言的變量類型要到程序運行時,待變量被賦值后,才具有某種類型。 而JavaScript是一門典型...
摘要:什么是面向對象本文不在論述。接下來說一下面向對象的三大特征在當中的實現。封裝實現封裝實現就是是對象內部的變化對外界是透明的不可見。這種做法使對象之間低耦合便于維護升級團隊協作開發。。 概述 本來打算寫設計模式的,在談論js的設計模式之前先說一下js的面向對象,因為很多設計模式的實現都摻雜著面向對象的思想,所以先做一下前期鋪墊。 js我們都知道是一種動態類型腳本型語言,變量類型無法保證,...
閱讀 2581·2021-11-22 12:01
閱讀 1105·2021-11-15 11:37
閱讀 3685·2021-09-22 14:59
閱讀 1746·2021-09-04 16:45
閱讀 1382·2021-09-03 10:30
閱讀 1013·2021-08-11 11:18
閱讀 2459·2019-08-30 10:53
閱讀 2013·2019-08-29 15:13