經過一個例子來聊今天的內容:bash
function Fun(){}
Fun.prototype.age = 18;
var f = new Fun();
console.log(f.age) // 18;
console.log(Fun.age) // undefined
複製代碼
爲何f.age的結果是18,而Fun.age的結果是undefined?函數
在開始以前,咱們先了解一下原型 、原型對象、__ proto__ 這三個概念。spa
原型(prototype):是指函數內部的一個屬性,這個屬性是個指針,指向原型對象。prototype
原型對象(prototype object):是指函數內部的一個對象,這個對象包含屬性和方法是共享的。指針
__ proto__([[prototype]]):是實例對象內部的一個屬性,它指向當前函數/Object類型的原型對象。code
它們之間的關係是:cdn
有兩個注意點:對象
它們之間的關係,咱們經過下面的圖來了解。 blog
經過上面的圖得出一些結論:原型鏈
全部的原型對象,都有constructor屬性,指向這個實例的構造函數;
函數的 prototype 屬性指向了一個對象,這個對象正是調用該構造函數而建立的原型對象;
__proto__指向原型鏈上一個節點的原型;
咱們所說的往原型鏈查找屬性或方法,是指"沿着.__proto __屬性找,而不是"沿着.prototype這個屬性去查找;
__ proto__ 和prototype是徹底不一樣的兩個東西; obj. __proto __ === 函數.prototype; 僅僅是說明,它們共同指向原型對象,僅此而已;
實例.__ proto__ 是構造函數.prototype,構造函數原型對象.__ proto__ 是Object.prototype;即:
obj.__ proto__ === Fn.prototype
obj.__ proto__.__proto__ === Fn.prototype.__proto__ === Object.prototype
複製代碼
函數.__ proto__ 是Function.prototype,Object類型. __proto __ 是Function.prototype;即:
Fn.__proto__ === Function.prototype
Object.__proto__ === Function.prototype
複製代碼
Function類型. __proto__是其自己;即:
Function.__ proto __ === Function.prototype
複製代碼
咱們再回頭看這個例子:
function Fun(){}
Fun.prototype.age = 18;
var f = new Fun();
console.log(f.age) // 18;
console.log(Fun.age) // undefined
複製代碼
爲何f.age的結果是18,而Fun.age的結果是undefined?
f.age:
由於,f是一個實例對象,f.age沒有值,則會往者f上一個節點的原型,f. __ proto __屬性找,
從上圖看是 Fun.prototype(注意,這是一個原型對象,而不是構造函數的prototype屬性==)
因此找到的結果是18。
Fun.age:
由於Fun是一個函數,這個函數上沒有定義.age屬性,(注意:Fun.prototype上的屬性 != Fun的屬性==),那這個時候,就會往Fun.__proto__屬性上找,
從上圖看是Function.protype(原型對象),也沒有找到,再往上找,直到頂端,而後返回undefined。
這回能明白上面的結果了嗎?