第一節中咱們介紹了javascript中的原型和原型鏈,這一節咱們來說利用原型和原型鏈咱們能夠作些什麼。javascript
var a = { x: 10, caculate: function(z) { console.log(this.x + this.y + z) } }; var b = { y: 20, __proto__: a }; var c = { y: 30, __proto__: a }; b.caculate(30) // 60 c.caculate(40) // 80
這樣咱們就經過的原型鏈實現了普通對象的繼承,下面咱們仍是經過一張原型圖來說解一下繼承的過程。
上面代碼中咱們建立了三個普通對象a、b、c,其中a有一個x屬性,和caculate方法;b和c都有一個y屬性,同時讓b和c的默認屬性__proto__屬性指向a對象,如圖所示。
這是時候咱們調用了b.caculate(30), c.caculate(40),顯然b和c的自身方法中是沒有caculate方法的,那麼這個時候就會沿着b的原型鏈向上查找,而後找到了a中有caculate方法,則返回caculate方法,
若是a中也沒有這個方法,那麼會沿着原型鏈繼續向上查找,找到則返回,找不到則返回undefinedhtml
好比咱們有一個名爲"Animal"的構造函數,還有一個叫作"Cat"的構造函數:前端
function Animal() {}; Animal.prototype.species = "動物"; function Cat(name, color) { this.name = name; this.color = color; }
其中Animal對象中有一個原型屬性species = "動物",Cat對象有兩個自身對象name和color,這個時候咱們若是須要讓Cat對象擁有Animal對象中的屬性應該怎麼辦呢? 很簡單咱們只須要讓Cat繼承Animal對象就好了,下面咱們看如何讓Cat繼承Animal:java
1 Cat.prototype= new Animal(); 2 Cat.prototype.constructor = Cat; 3 var cat1 = new Cat("大白", "白色") 4 console.log(cat1.species) // 動物
上面的方法是經過直接繼承prototype的方法實現的繼承,如上圖所示:咱們一開始建立Cat對象時,Cat.prototype默認指向Cat的原型(如步驟1所示)。 而後咱們更改Cat的原型鏈,讓Cat.prototype指向Animal 的實例(實例中具備構造函數的全部屬性和方法),如步驟2所示,這樣就成功更改了Cat的原型鏈,當咱們調用Cat.species屬性時,沿着原型鏈就查找到Animal實例中的species屬性了,這樣就實現了函數對象的繼承。
固然這還沒完,由於咱們還有重要的一步沒完成,沒錯!就是上面的第2行代碼,若是沒有這行代碼Animal實例中的constructor指針是指向Animal構造函數的,這樣顯然是不對的,由於constructor正常狀況下應該指向它的構造函數,所以咱們須要手動更改:Cat.prototype.constructor = Cat; 使constructor從新指向Cat對象。segmentfault
咱們這裏講的繼承的方法只是常見的一種,另外還有多種方法實現繼承,這裏推薦阮一峯的一篇文章:構造函數的繼承,裏面講了常見的實現繼承的方法。這篇文章也是參考了裏面的方法。函數
若是看了這兩篇文章,你仍是沒搞清楚原型和原型鏈,給你推薦我學習的時候看的幾篇文章,反覆的看反覆的閱讀,總會弄明白的,畢竟我是花了三天時間才搞懂了。
最詳盡的 JS 原型與原型鏈終極詳解
深刻理解JavaScript系列(10):JavaScript核心(晉級高手必讀篇)
前端開發必須知道的JS(一) 原型和繼承學習