1. 程式人生 > 實用技巧 >【面向物件】面向物件之方法繼承(五)

【面向物件】面向物件之方法繼承(五)

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、寄生繼承

在網上會經常見到一種方法叫做寄生繼承。其實看到名字你也能想的到,一定需要一個類似寄生器一樣的東西。其實就是一箇中間函式