面向對象編程都會涉及到繼承這個概念,JS中實現繼承的方式主要是經過原型鏈的方法。javascript
每建立一個函數,該函數就會自動帶有一個 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
前面咱們說到,全部的實例有一個內部指針,指向它的原型對象,而且能夠訪問原型對象上的全部屬性和方法。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 高級程序設計》