與大部分面嚮對象語言不一樣,ES6以前中並無引入類(class)的概念,JavaScript並不是經過類而是直接經過構造函數來建立實例。在介紹原型和原型鏈以前,咱們有必要先複習一下構造函數的知識。git
構造函數模式的目的就是爲了建立一個自定義類,而且建立這個類的實例。構造函數模式中擁有了類和實例的概念,而且實例和實例之間是相互獨立的,即實例識別。github
構造函數就是一個普通的函數,建立方式和普通函數沒有區別,不一樣的是構造函數習慣上首字母大寫。另外就是調用方式的不一樣,普通函數是直接調用,而構造函數須要使用new關鍵字來調用。bash
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
this.sayName = function () {
alert(this.name);
}
}
var per = new Person("孫悟空", 18, "男");
function Dog(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
var dog = new Dog("旺財", 4, "雄")
console.log(per);//當咱們直接在頁面中打印一個對象時,事件上是輸出的對象的toString()方法的返回值
console.log(dog);
複製代碼
每建立一個Person構造函數,在Person構造函數中,爲每個對象都添加了一個sayName方法,也就是說構造函數每執行一次就會建立一個新的sayName方法。這樣就致使了構造函數執行一次就會建立一個新的方法,執行10000次就會建立10000個新的方法,而10000個方法都是一摸同樣的,爲何不把這個方法單獨放到一個地方,並讓全部的實例均可以訪問到呢?這就須要原型(prototype
)函數
在JavaScript中,每當定義一個函數數據類型(普通函數、類)時候,都會天生自帶一個prototype
屬性,這個屬性指向函數的原型對象,而且這個屬性是一個對象數據類型的值。學習
讓咱們用一張圖表示構造函數和實例原型之間的關係:this
__proto__
和constructor
每個對象數據類型(普通的對象、實例、prototype
......)也天生自帶一個屬性__proto__
,屬性值是當前實例所屬類的原型(prototype
)。原型對象中有一個屬性constructor
, 它指向函數對象。spa
function Person() {}
var person = new Person()
console.log(person.__proto__ === Person.prototype)//true
console.log(Person.prototype.constructor===Person)//true
//順便學習一個ES5的方法,能夠得到對象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
複製代碼
在JavaScript中萬物都是對象,對象和對象之間也有關係,並非孤立存在的。對象之間的繼承關係,在JavaScript中是經過prototype對象指向父類對象,直到指向Object對象爲止,這樣就造成了一個原型指向的鏈條,專業術語稱之爲原型鏈。prototype
舉例說明:person → Person → Object ,普通人繼承人類,人類繼承對象類code
當咱們訪問對象的一個屬性或方法時,它會先在對象自身中尋找,若是有則直接使用,若是沒有則會去原型對象中尋找,若是找到則直接使用。若是沒有則去原型的原型中尋找,直到找到Object對象的原型,Object對象的原型沒有原型,若是在Object原型中依然沒有找到,則返回undefined。cdn
咱們可使用對象的hasOwnProperty()
來檢查對象自身中是否含有該屬性;使用in
檢查對象中是否含有某個屬性時,若是對象中沒有可是原型中有,也會返回true
function Person() {}
Person.prototype.a = 123;
Person.prototype.sayHello = function () {
alert("hello");
};
var person = new Person()
console.log(person.a)//123
console.log(person.hasOwnProperty('a'));//false
console.log('a'in person)//true
複製代碼
person實例中沒有a這個屬性,從 person 對象中找不到 a 屬性就會從 person 的原型也就是 person.__proto__
,也就是 Person.prototype中查找,很幸運地獲得a的值爲123。那假如 person.__proto__
中也沒有該屬性,又該如何查找?
當讀取實例的屬性時,若是找不到,就會查找與對象關聯的原型中的屬性,若是還查不到,就去找原型的原型,一直找到最頂層Object爲止。Object是JS中全部對象數據類型的基類(最頂層的類)在Object.prototype上沒有__proto__
這個屬性。
console.log(Object.prototype.__proto__ === null) // true
複製代碼