Js 原型,原型鏈

原型,原型鏈函數

 

原型:在JavaScript中原型是一個prototype對象,用於表示類型之間的關係。學習

 

原型鏈:JavaScript萬物都是對象,對象和對象之間也有關係,並非孤立存在的。對象之間的繼承關係,在JavaScript中是經過prototype對象指向父類對象,直到指向Object對象爲止,這樣就造成了一個原型指向的鏈條,專業術語稱之爲原型鏈。this

 

 

示例:

咱們先使用構造函數建立一個實例對象 person :spa

function Person() {}

var person = new Person(); person.name = 'name'; console.log(person.name) // name

在這個例子中,Person就是一個構造函數,咱們使用new建立了一個實例對象person。接下來prototype

 

prototype 原型code

每一個函數都有一個prototype屬性,就是咱們常常在各類例子中看到的那個prototype,好比:對象

function Person() {}

// 雖然寫在註釋裏,可是你要注意:prototype是函數纔會有的屬性
 Person.prototype.name = 'name'; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // name  console.log(person2.name) // name

那這個函數的prototype屬性到底指向的是什麼呢?blog

其實,函數的prototype屬性指向了一個對象,這個對象正是調用該構造函數而建立的實例的原型,也就是這個例子中的person1和person2的原型。繼承

那麼什麼是原型呢?你能夠這樣理解:每個JavaScript對象(null除外)在建立的時候就會與之關聯另外一個對象,這個對象就是咱們所說的原型,每個對象都會從原型」繼承」屬性。ip

讓咱們用一張圖表示構造函數和實例原型之間的關係:

那麼咱們該怎麼表示實例與實例原型,也就是person和Person.prototype之間的關係呢,這時候咱們就要講到第二個屬性:

__proto__ 

這是每個JavaScript對象(除了null)都具備的一個屬性,叫__proto__,這個屬性會指向該對象的原型。

爲了證實這一點,咱們能夠在谷歌控制檯中輸入:

function Person() {}

var person = new Person(); console.log(person.__proto__ === Person.prototype); //true

因而咱們更新下關係圖:

 

既然實例對象和構造函數均可以指向原型,那麼原型是否有屬性指向構造函數或者實例呢 ?答案固然是有的,但也不全然 :

指向實例卻是沒有,由於一個構造函數能夠生成多個實例,可是原型指向構造函數卻是有的,這就要講到第三個屬性:construcotr,每一個原型都有一個constructor屬性指向關聯的構造函數

 constructor

爲了驗證這一點,咱們一樣能夠在谷歌控制檯嘗試:

function Person() {}

console.log(Person === Person.prototype.constructor); //true

因此再更新下關係圖:

綜上咱們已經得出:

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

瞭解了構造函數、實例原型、和實例對象之間的關係,接下來咱們講講實例和原型的關係:

 

實例與原型

當讀取實例的屬性時,若是找不到,就會查找與實例對象關聯的原型中的屬性,若是還查不到,就去找原型的原型,一直找到最頂層爲止。

舉個例子:

function Person() {}

Person.prototype.name = 'name'; var person = new Person(); person.name = 'name of this person'; console.log(person.name) // name of this person //刪除 person.name ; 則會找原型中的name delete person.name; console.log(person.name) // name

在這個例子中,咱們設置了person的name屬性,因此咱們能夠讀取到爲’name of this person’,當咱們刪除了person的name屬性時,讀取person.name,從person中找不到就會從person的原型也就是person.__proto__ == Person.prototype中查找,幸運的是咱們找到了爲’name’,可是萬一尚未找到呢 ?原型的原型又是什麼呢 ?

在前面,咱們已經講了原型也是一個對象,既然是對象,咱們就能夠用最原始的方式建立它,那就是:

var obj = new Object();

obj.name = 'name' console.log(obj.name) // name

因此原型對象是經過Object構造函數生成的,結合以前所講,實例的__proto__指向構造函數的prototype,因此咱們再更新下關係圖:

 

 

 

原型鏈

那Object.prototype的原型呢?

null,就是null,因此查到Object.prototype就能夠中止查找了

因此最後一張關係圖就是

 

最後說一下,圖中由相互關聯的原型組成的鏈狀結構就是原型鏈,也就是藍色的這條線。

相關文章
相關標籤/搜索