【面向物件】面向物件之方法繼承(五)
阿新 • • 發佈:2020-08-12
001原型鏈
什麼是原型鏈? 解釋:由__proto__形成的鏈條叫做原型鏈 假設我們建立了一個Person這個建構函式,然後例項化出一個物件fanchen,當我們輸出這個例項化物件的時候,這個例項化物件裡面有一個__proto__屬性,這個__proto__屬性指向的是建立自己的那個建構函式的原型,也就是說這個例項化物件的__proto__指向的是Person裡面的prototype這個原型物件,因為prototype是一個物件因此裡面肯定也會有一個__proto__。而這個__proto__指向的是建立Person這個建構函式的物件,可以想象一下誰建立了Person?這個時候我們就不得不說一句"萬物皆是物件".肯定是一個物件建立了Person。而這個物件就是 Function。有物件那麼肯定就會有__proto__.那麼我們可以想象一下還有什麼可以創建出來物件嗎?因此物件的頂端也就是null.接下來我們用案例和記憶體圖詳細的解釋一波
總結: 原型鏈:由__proto__形成的鏈條 Object裡面的__proto__指向的是null
002方法繼承
繼承: 在上一章我們說了屬性繼承,接下來我們繼續說下方法繼承。方法的繼承分為好多種,接下來我們逐個分析來找出一種最完美的繼承方式 首先我們還是回顧一下屬性繼承,我們先寫一個建構函式Person。然後再建立1個例項化物件fanchen
現在我們可以繼承到父級的屬性了,但是貌似父級的方法繼承不了,因為我看到__proto__裡面只有一個work這個方法。那麼我們如何繼承父級的方法呢?我們可以試想一樣fanchen是如何訪問到work這個方法的?因為例項化物件裡面的__proto__指向是建立自己的那個建構函式的原型物件因此可以訪問。那麼如果現在我用Man的原型物件指向Person的原型物件會發生什麼?
1、原型繼承
Man的原型物件指向Person的原型物件
貌似是可以的,但是這個原理是什麼呢?同時注意一下上面的constructor的指向。接下來我們畫一個記憶體圖來解釋一下原理和弊端。
從上面的記憶體圖中我們不難看出當Man的原型指向Person的原型的時候首先Man的原型物件斷掉了,隨後我們又給Man的原型添加了方法work,這個時候你會發現Man的work方法加到了Person身上。這樣肯定是不行的,因為我們怎麼能修改父級的原型物件呢?順便我們可以在打印出來父級的原型看一下
因此這個原型繼承肯定是不行的,那麼接下來我們說下原型繼承缺點 缺點:子類原型發生改變父類原型也會發生改變2、原型拷貝
上面的方法肯定不是特別合理的,那麼我們可以想一下既然不能直接將Man的原型指向Person的原型,那麼我們可不可將Person裡面原型物件的屬性直接拷貝一份,這樣我就不會直接修改到父級的原型了? 廢話少說直接上程式碼
貌似特別完美,接下來我們在檢視一下父級有沒有發生改變
真的沒有什麼問題啊。那麼接下來我們通過記憶體圖來檢視下原理及缺點
從記憶體圖中可以看出我們的Man只是拷貝了一份Person的方法,然後Man裡面的方法的指向還是指向Person的裡面方法的原型。隨後我們又在Man上面添加了一個work方法。這樣我們既不會汙染Person也能實現了繼承,但是缺點也顯而易見了 缺點:假設Person上面還有父級 那麼我們的Man是無法訪問到Person父級的原型上的方法3、原型鏈繼承
從上一章我們講的原型鏈可以知道,我們可以通過原型鏈訪問父級以及父父級裡面的一些屬性和方法,那麼我們利用這個特點可以將Man的原型物件指向Person的一個例項.因為例項裡面肯定是有一個__proto__,這樣的話我們就形成了一個原型鏈。接下來我們用案例和記憶體圖來表示
當打印出來的時候確實可以看到父級的方法也可以進行訪問,但是有缺點,大家不難發現Man的__proto__裡面多了幾個age name sex 而且值還是undefined?
4、混合繼承
從上面的原型鏈繼承可以看出,當打印出來fanchen的時候我們丟失了一個constructor屬性而且還有好多雜亂的屬性,那麼我們應該如何解決呢?我們一步一步來
這時候你就會發現終於實現了完美繼承。
5、寄生繼承
在網上會經常見到一種方法叫做寄生繼承。其實看到名字你也能想的到,一定需要一個類似寄生器一樣的東西。其實就是一箇中間函式