標籤:技術分享 基礎 看到了 com 上下 const prototype 構造 自己的
我們已經描述了對象的建立,那麼接下來主要講解對象的結構和對象的屬性。首先我們先看下對象和類的結構圖Person類 person的一個執行個體 那麼在上面,我們稱變數 p 是 Person類的一個執行個體(大家在學習或者其他的視頻教學時經常聽到 建立一個執行個體對象就是這麼來的)。 在p和Person之間,通過在建立new Person的時候為對象p添加了兩個主要的屬性。constructor:構造器 用來指向當前對象建立時,所調用的函數。__proto__:原型指標屬性.通常用來指向當前建構函式的prototype屬性(Object.create的指向會有所趨避=>其實我不想寫的 就怕有人糾結這個問題). ok~那麼我們在上面已經簡單看到了constructor的指向,就可以知道p是哪個函數建立的 那__proto__屬性是幹什麼的呢?我們來看下面兩個例子 我們以Person為建構函式分別建立兩個執行個體,並且在zhang的時候傳入對應的屬性參數,在li的時候不傳入參數,並做列印。 在看到結果的時候我們很明顯的能發現兩個小的問題.1.new Person時 ,this對象會每次進行調用建立屬性和方法,效能差2.我們的兩個對象都是person類所建立的,缺少共有的方法和屬性。補:比如每個人都會想··人應該有眼睛鼻子耳朵,那麼這些東西我們不用特定的給予也應該存在,倆耳朵一個鼻子倆眼睛(特殊情況就算了) 所以我們需要使用原型模式來建立對象的共有屬性和方法。 下面我們單獨使用原型方式來建立一個人的類
最終的結果我們發現兩者完全一樣 這是因為js中建立對象,如果當前對象缺少私人屬性的時候,如上面z和s本身是沒有name屬性的,name就會通過__proto__尋找建構函式的prototype對象下對應的屬性或方法(對象本身是可以繼承的,如果Person的原型也沒有name屬性,就會通過Person函數的__proto__去尋找,以此類推,因為js中所有的類最終都會指向Object對象,所以我們經常看到建立一個對象會預設攜帶.toString、length、name和其他的屬性方法)。 那如果當前對象有私人的屬性和方法會怎麼辦呢?我們是不是只要用prototype就好了,不需要在使用this建立了呢?也不是的,來看下面的兩個例子(為了保持代碼的完整性,My Code結構可能貼的比較多 大家忍耐下) 代碼: 輸出: 在這裡有兩個小小的問題:1.使用prototype添加屬性和方法時,代碼量明顯爭奪2.如果大家在認真看對比資料的情況下就能很明顯有些資料結構不太明確了 那對於這裡的解釋··其實我也很無力,畢竟物件導向,不是補基礎課程,我簡單說下,理解不了的就死記硬背吧。1.通過z.name=是重新賦值,添加的是私人屬性,而name屬性是實值型別,會單獨建立一塊空間資料結構。2.z.girlFriends.push 是調用屬性增加資料結構的變數,那z本身是沒有girlFriends的屬性的,所以會通過__proto__預設指向Person.prototype下的girlFriends並在尾部追加一個變數。那當我們調用s.girlFriends的時候,因為本身沒有對應的屬性和方法,所以就會通過__proto__指向Person.prototype下的屬性,該死的Person.prototype.girlFriends唄z給更改了,所以最後s和z的girlFriends就會是一樣的。3.那大家說··如果我使用z.girlFriends = "";會怎麼樣的?那z會和Person.prototype下的girlFriends脫節,因為 = 代表的是添加私人屬性 重新賦值.注:建議大家好好看看實值型別和引用資料類型的區別與概念,還是蠻有用的 所以根據__proto__的特性和代碼複用的原則,我們一般使用組合模式用來建立一個對象的建構函式。 那麼我們再看看對象的一些其他屬性:this:在使用new關鍵字時,this會更改上下文指向當前我們新建立的執行個體。isPrototypeOf:判斷對象A是否為對象B的原型對象(B.__protot__是否指向A)。如上面代碼格式應該為(好好讀代碼):
hasOwnerPrototype:判斷當前執行個體對象是否存在自己的私人屬性 in:判斷一個對象中是否包含屬性或函數(通過__proto__指向的也包含在內)
javascript物件導向(二)