prototype原型對象
每個函數都有一個默認的prototype
屬性,其實際上還是一個對象,如果被用在繼承中,姑且叫做原型對象。
在構造函數中的prototype
中定義的屬性和方法,會被創建的對象所繼承下來。舉個栗子:
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
?來實現這種繼承)。
神秘的__proto__
JS的對象中都包含了一個__proto__
屬性,其指向的是創建該對象時的構造函數的原型對象prototype。
從上面的輸出結果看出,f.__proto__
指向了其構造函數F的prototype
,而F.prototype
本身也是一個對象,其內部也有__proto__
屬性,其指向的是Object.prototype
,直到最后Object.prototype
指向null
,這條原型鏈才結束。
因此,__proto__
這個神秘的屬性才是原型鏈形成的真正原因。
原型鏈
由于原型對象本身也是對象,根據上邊的定義,它也有自己的原型,而它自己的原型對象又可以有自己的原型,這樣就組成了一條鏈,這個就是原型鏈,JavaScritp引擎在訪問對象的屬性時,如果在對象本身中沒有找到,則會去原型鏈中查找,如果找到,直接返回值,如果整個鏈都遍歷且沒有找到屬性,則返回undefined。原型鏈一般實現為一個鏈表,這樣就可以按照一定的順序來查找。
下面是一張經典的圖:
從上圖看出:
Object.prototype
是頂級對象,所有對象都繼承自它。Function
?繼承?Function
?本身,?Function.prototype
?繼承?Object.prototype
?。Function.prototype
?和?Function.__proto__
?都指向?Function.prototype
Object.prototype.__proto__
?===?null
?,說明原型鏈到?Object.prototype
?終止。