在瞭解JS原型對象之前,我們需要了解一些基礎知識:
首先是構造函數,我們要知道構造函數的幾個特點
- 構造函數的首字母必須大寫 ,區分於其他普通函數
- 內部使用的this對象,指向即將要生成的實例對象。
- 使用new來生成實例對象
由此我們可以得到,任何函數只要通過new操作符來調用,那這個函數就可以稱爲構造函數。
// 文章中之後的知識點都是以這個函數作爲基礎
function Person(name, age){
this.name = name;
this.age = age;
}
var person1 = new Person('Echo', 19);
var person2 = new Person('Jose', 18);
如上代碼所示,由於在實例化person1和person2的時候,我們通過new操作符來調用Person,所以Person這個函數就是構造函數。
所以person1和person2都是Person的實例,在實例化person1和person2的時候,會自動獲得一個constructor屬性,這個屬性是一個指針,指向Person。
person1.constructor === Person; // true
person2.constructor === Person; // true
由上面的實驗,所以我們可以得到一個定律:
1: 實例的構造函數屬性指向構造函數 => person1.constructon === Person;
在JS中,每個函數對象在創建的時候,都會自動分配一個 prototype屬性,這個屬性指向函數的原型對象,
需要注意的是:
2:每個對象都會有_proto_屬性,但是隻有函數對象纔有prototype屬性(除Function.prototype外);
(Function.prototype是函數對象,但是它沒有prototype屬性)
那什麼是原型對象呢,其實原型對象也是一個普通對象,在上面的函數中,Person.prototype就是原型對象,
原型對象默認會獲得一個constructor(構造函數)屬性,而這個屬性是一個指針,指向prototype屬性所在的函數,所以我們可以得到:
Person.prototype.constructor === Person
而我們知道:
person1.constructor === Person;
爲什麼person1也有constructor屬性呢,因爲person1是Person的實例;
那爲什麼Person.prototype也有constructor屬性呢,我們可以把Person.prototype想象是Person的實例;
也就是說,Person在創建的時候,創建了一個它的實例對象並賦值給它的prototype:
let A = new Person();
Person.prototype = A;
此時,我們可以得出結論:
原型對象(Person.prototype)是構造函數(Person)的一個實例;