每一個函數都有一個默認的prototype
屬性,其實際上仍是一個對象,若是被用在繼承中,姑且叫作原型對象。函數
在構造函數中的prototype
中定義的屬性和方法,會被建立的對象所繼承下來。舉個栗子:spa
function F(){} F.prototype.work = function(){ console.log('F is working..'); }; var f = new F(); f.work(); // F is working..
當你建立函數時,JS會爲這個函數自動添加 prototype
屬性,值是空對象。而一旦你把這個函數看成構造函數( constructor
)調用(即經過 new 關鍵字調用),那麼JS就會幫你建立該構造函數的實例,實例繼承構造函數 prototype
的全部屬性和方法(實例經過設置本身的 __proto__
指向承構造函數的 prototype
來實現這種繼承)。prototype
__proto__
JS的對象中都包含了一個__proto__
屬性,其指向的是建立該對象時的構造函數的原型對象prototype。code
從上面的輸出結果看出,f.__proto__
指向了其構造函數F的prototype
,而F.prototype
自己也是一個對象,其內部也有__proto__
屬性,其指向的是Object.prototype
,直到最後Object.prototype
指向null
,這條原型鏈才結束。對象
所以,__proto__
這個神祕的屬性纔是原型鏈造成的真正緣由。繼承
因爲原型對象自己也是對象,根據上邊的定義,它也有本身的原型,而它本身的原型對象又能夠有本身的原型,這樣就組成了一條鏈,這個就是原型鏈,JavaScritp引擎在訪問對象的屬性時,若是在對象自己中沒有找到,則會去原型鏈中查找,若是找到,直接返回值,若是整個鏈都遍歷且沒有找到屬性,則返回undefined。原型鏈通常實現爲一個鏈表,這樣就能夠按照必定的順序來查找。ip
下面是一張經典的圖:原型鏈
從上圖看出:原型
Object.prototype
是頂級對象,全部對象都繼承自它。it
Function
繼承 Function
自己, Function.prototype
繼承 Object.prototype
。
Function.prototype
和 Function.__proto__
都指向 Function.prototype
Object.prototype.__proto__
=== null
,說明原型鏈到 Object.prototype
終止。