弄清原型和原型鏈

四條大規則

原型和原型鏈,大致能夠用如下幾條規則歸納,弄清楚了這幾條,也就基本吃透了原型和原型鏈。函數

  1. 全部的引用類型都有一個__proto__屬性,屬性值是一個普通對象
  2. 全部的函數都有一個prototype屬性,屬性值也是一個普通對象
  3. 全部引用類型的__proto__屬性值指向其構造函數的prototype屬性值
  4. 當試圖獲得一個對象的某個屬性值時,若是這個對象自己沒有該屬性,就會去它的__proto__(它構造函數的prototype)中查找

(爲了方便起見,下文中__proto__用隱式原型代替,prototype用顯式原型代替)
舉個栗子:this

// 構造函數
function Human(name) {
    this.name = name;
}
Human.prototype.introduce = function(){
    console.log('My name is', this.name);
}

var somebody = new Human('somebody');
console.log(Human.prototype); // Function
console.log(Human.prototype.constructor === Human); // true
console.log(somebody.__proto__ === Human.prototype);  // true
somebody.introduce(); // "My name is somebody"

在上述例子中,Human是構造函數,而somebody是Human的一個實例。從console輸出結果能夠驗證,構造函數的顯式原型的constructor屬性指向它自己,實例的隱式原型屬性指向其構造函數的顯式原型。spa

在實例somebody中並無introduce方法,該方法實際是在Human.prototype中,由上述第四條,當試圖獲得一個對象的某個屬性值時,若是這個對象自己沒有該屬性,就會去它的__proto__(它構造函數的prototype)中查找,因此somebody的introduce方法其實是somebody.__proto__.introduce,也就是Human.prototype.introduce。prototype

上圖幫助理解吧~
原型及原型鏈code

實例的隱式原型屬性指向其構造函數的顯式原型屬性。
全部的一層一層的__proto__連起來,就構成了原型鏈。例如,在Object.prototype上有一方法toString,而somebody也有,但其實somebody的toString方法並不是自身全部(除非單獨有聲明),而是來自於somebody.__proto__.__proto__.__proto__(即Object.prototype),這一點能夠經過hasOwnProperty證實。對象

原型相關方法

判斷一個對象是否在原型鏈上能夠用instanceof,判斷某一個屬性是不是自身屬性能夠用hasOwnProperty。blog

console.log(somebody.hasOwnProperty('name')) // true
console.log(somebody instanceof Object); // true

//語法
// obj.hasOwnProperty(prop)
// object instanceof constructor

後續再出一期與new運算符相關的還有與原型繼承、class相關的吧,排期ing。繼承

參考閱讀

MDN: instanceof
MDN: constructor
MDN: hasOwnPropertyip

相關文章
相關標籤/搜索