在傳統的面向對象的編程語言中,有很好的方法可以判斷一個實例對象屬於哪一個類,可是在js中,並無完美方法來實現這個功能,可是仍是有幾種方法來彌補,下面介紹3種:程序員
a.instanceof運算符和isPrototype()方法,編程
instanceof操做符的左操做數是待檢測其類的對象,右操做數是定義類的構造函數,若是o繼承自c.prototype,則表達式 o instanceof c 返回true.,此外當o繼承自一個也繼承自c.prototype的對象時也會返回true;一樣的isPrototype()方法也能實現相似功能,即在多個執行上下文場景中沒法正常工做。數組
可是着兩個都沒法經過對象來得到類名,此外在客戶端JavaScript中,出現多窗口和多框架子頁面中兼容性不佳框架
b.constructor屬性編程語言
這個屬性在上一篇中剛剛提到過,用這個屬性能夠得到類名,但在多個執行上下文中的場景中也沒法政策工做,並且並非全部的對象中都具備這個屬性。函數
c。使用構造函數的函數名spa
上述的兩類方法在用來檢測對象所屬類中都有「多個執行上下文場景中沒法正常工做」的問題,一種可能的解決方案是使用構造函數名稱字符串,可是這樣作在當構造函數沒有名稱的時候也沒法正常工做。prototype
鴨式辯型這個思考問題的方式是由James Riley提出的,它的思想是:像鴨子同樣走路,游泳而且嘎嘎叫的鳥就是鴨子。code
對於程序員來講:不要關注對象類型是什麼,而是關注對象能作什麼。拿上一篇中的例二來講,Range中的includes方法並無對實參進行類型檢測以確保它是數字類型,就直接拿來比較;此外在類數組對象中這點顯得尤其明顯,在不少場景蝦,咱們並不知道一個對象是否爲數組對象,能夠經過判斷該對象是否包含一個length的屬性,有就認爲它是數組對象,即這隻「鴨子」會游泳了,會不會走路和嘎嘎叫則不去判斷。對象
鴨式辯型的實現方法讓人感受太「聽任自流」:僅僅是假設輸入的對象實現了必要的方法,沒有進一步執行檢查。若是輸入對象沒有遵循以前的「假設」,那麼當代碼試圖調用那些根本不存在的方法時就會報錯;另外一種實現方法是對輸入對象進行檢查,但不是檢查它們的類,而是用適合的名字來檢查它們所實現的方法,這樣能夠將非法輸入儘量的攔截在前,並給出有效提示,請看下面的例子:
1 function quacks(o /*,...*/){ 2 for (var i = 1; i < arguments.length; i++) { 3 var arg = arguments[i]; 4 switch(typeof arg){ 5 case "string" : //直接用名字作檢查 6 if(typeof o[arg] !== "function") return false; 7 continue; 8 case "function" : 9 arg = arg.prototype; 10 continue; 11 case "object": 12 for(var m in arg){ 13 if(typeof arg[m] !== "function") continue; 14 if(typeof o[m] !== "function") return false; 15 } 16 continue; 17 } 18 } 19 return true; 20 }
關於這個quacks函數有亮點須要注意:咱們只是經過給定的名稱來檢測對象是否知足要求,但沒法得知其細節,而這也正是鴨式辯型的本質所在;此外該函數該函數不能應用於內置類,由於內置類中的方法都是沒法經過for/in來遍歷的。
到此爲止,算上以前5篇,再加上這一篇基本上以及把JavaScript中的面向對象的基礎介紹完了,接下來會介紹些JavaScript中關於面向對象編程的技術,固然仍是基於David Flanagan大神的那本《JavaScript權威指南》。