js中的原型鏈是一個很重要的概念,理解了原型鏈,對js程序的開發有很大的好處,廢話不說,先上圖:javascript
javascript是基於原型的語言,因此一個對象能夠另外一個對象繼承。不過javascript實現的時候有些周折,它並非直接讓一個對象繼承自另外一個對象。而是模仿其它基於類的語言,java
也是生成構造函數。只不過javascript沒有顯示的聲明函數,javascript的每一個函數均可以當構造函數。在函數調用的時候,只要在前面加上new操做符就生成了一個實例,其實也是函數
一個對象。這個對象有一個內部屬性__proto__指向了一個原型對象。當咱們運行程序訪問咱們新建對象的屬性或方法時,首先會在咱們新建的對象裏尋找該屬性或方法,若是找到則this
返回,若是沒找到,則會經過該對象的__proto__屬性,查找其原型對象有沒有咱們須要的屬性或方法。prototype
那咱們新聲明的對象的__proto__到底指向的是那個原型對象那?咱們結合上圖的例子看一下。對象
拿上面的構造函數A舉例,函數A被建立時,A會附帶生成一個prototype的屬性,這個屬性指向的對象用代碼表示應該是:A.prototype = { constructor : A }。blog
new A()的__proto__屬性就指向了A.prototype。那麼在調用new運算符的時候發生了什麼那?《javascript語言精粹》一書中說的很是好,想看詳情的請移步這本書的第五章啊!繼承
若是把new運算符當作一個方法,它的執行過程多是這樣的:ip
a、首先會建立一個新對象,將新對象的__proto__屬性指向A.prototype。原型鏈
b、調用構造函數A,綁定this到咱們新建立的對象。
c、判斷函數A調用後有沒有是對象類型的返回值,若是有則返回該對象;若是沒有則返回咱們建立的新對象。
因此,雖然javascript是基於原型的語言,可是它並無直接讓對象從其餘對象繼承,而多了一步經過構造函數產生對象,再繼承其餘對象的步驟。
經過上圖,還有咱們須要注意的一些點:
一、在javascript裏函數就是對象,只不過它比其餘普通對象多了兩個隱藏的屬性:函數上下文和調用函數代碼的調用屬性而已。上圖中構造函數A就是Function的一個實例,
一樣Object也是。
二、實例,構造函數,原型對象三者之間的關係要注意。實例和構造函數之間並無什麼直接關係。
三、經過對象的__proto__屬性在查找屬性時,若是找不到,會一直往上查找,直到Object.prototype這個根對象。
四、Function.prototype === Function.__proto__ ; Function是其自身的構造函數。即:Function.constructor === Function。
最後留個問題,結合上圖,Object instanceof Object; Function instanceof Function; Object instanceof Function; Function instanceof Object,的值分別是?why?