js繼承之原型繼承

面向對象編程都會涉及到繼承這個概念,JS中實現繼承的方式主要是經過原型鏈的方法。javascript

1、構造函數、原型與實例之間的關係

  每建立一個函數,該函數就會自動帶有一個 prototype 屬性。該屬性是個指針,指向了一個對象,咱們稱之爲 原型對象。什麼是指針?指針就比如學生的學號,原型對象則是那個學生。咱們經過學號找到惟一的那個學生。假設忽然,指針設置 null, 學號重置空了,不要慌,對象還存在,學生也沒消失。只是很差找了。html

  原型對象上默認有一個屬性 constructor,該屬性也是一個指針,指向其相關聯的構造函數。java

  經過調用構造函數產生的實例,都有一個內部屬性,指向了原型對象。因此實例可以訪問原型對象上的全部屬性和方法。編程

  

  因此三者的關係是,每一個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。通俗點說就是,實例經過內部指針能夠訪問到原型對象,原型對象經過constructor指針,又能夠找到構造函數。函數

  下面看一個例子:this

function Dog (name) {
    this.name = name;
    this.type = 'Dog';  
}
Dog.prototype.speak = function () {
  alert('wang');
}
var doggie = new Dog('jiwawa');
doggie.speak();  //wang 

   以上代碼定義了一個構造函數 Dog(),  Dog.prototype 指向的原型對象,其自帶的屬性construtor又指回了 Dog,即  Dog.prototype.constructor == Dog. 實例doggie因爲其內部指針指向了該原型對象,因此能夠訪問到 speak方法。spa

 

  Dog.prototype 只是一個指針,指向的是原型對象,可是這個原型對象並不特別,它也只是一個普通對象。假設說,這時候,咱們讓 Dog.protptype 再也不指向最初的原型對象,而是另外一個類 (Animal)的實例,狀況會怎樣呢?prototype

 

2、原型鏈

  前面咱們說到,全部的實例有一個內部指針,指向它的原型對象,而且能夠訪問原型對象上的全部屬性和方法。doggie實例指向了Dog的原型對象,能夠訪問Dog原型對象上的全部屬性和方法;若是Dog原型對象變成了某一個類的實例 aaa,這個實例又會指向一個新的原型對象 AAA,那麼 doggie 此時就能訪問 aaa 的實例屬性和 AA A原型對象上的全部屬性和方法了。同理,新的原型對象AAA碰巧又是另一個對象的實例bbb,這個實例bbb又會指向新的原型對象 BBB,那麼doggie此時就能訪問 bbb 的實例屬性和 BBB 原型對象上的全部屬性和方法了。設計

  這就是JS經過原型鏈實現繼承的方法了。看下面一個例子:指針

//定義一個 Animal 構造函數,做爲 Dog 的父類
function Animal () {
    this.superType = 'Animal';
}

Animal.prototype.superSpeak = function () {
    alert(this.superType);
}

function Dog (name) {
    this.name = name;
    this.type = 'Dog';  
}
//改變Dog的prototype指針,指向一個 Animal 實例
Dog.prototype = new Animal(); //上面那行就至關於這麼寫
//var animal = new Animal();
//Dog.prototype = animal;

Dog.prototype.speak = function () {
  alert(this.type);
}
var doggie = new Dog('jiwawa');
doggie.superSpeak();  //Animal 

  解釋一下。以上代碼,首先定義了一個 Animal 構造函數,經過new Animal()獲得實例,會包含一個實例屬性 superType 和一個原型屬性 superSpeak。另外又定義了一個Dog構造函數。而後狀況發生變化,代碼中加粗那一行,將Dog的原型對象覆蓋成了 animal 實例。當 doggie 去訪問superSpeak屬性時,js會先在doggie的實例屬性中查找,發現找不到,而後,js就會去doggie 的原型對象上去找,doggie的原型對象已經被咱們改爲了一個animal實例,那就是去animal實例上去找。先找animal的實例屬性,發現仍是沒有 superSpeack, 最後去 animal 的原型對象上去找,誒,這才找到。

(但願這張圖對你們的理解有幫助吧。) 

  

  這就說明,咱們能夠經過原型鏈的方式,實現 Dog 繼承 Animal 的全部屬性和方法。

  總結來講:就是當重寫了Dog.prototype指向的原型對象後,實例的內部指針也發生了改變,指向了新的原型對象,而後就能實現類與類之間的繼承了。(可是若是在重寫原型對象以前,產生的實例,其內部指針指向的仍是最初的原型對象。這個我下次再發篇文章講。js 繼承之借用構造函數繼承

 

若是你以爲文章解決了你的疑惑的話,還請賞我一個推薦哦~  :)

做者不才,文中如有錯誤,望請指正,避免誤人子弟。

文章內容全都參考於《JAVASCRIPT 高級程序設計》

相關文章
相關標籤/搜索