上一篇講了javascript
①原型對象是什麼;java
②__proto__
、prototype
、constructor
的關係;瀏覽器
③原型對象的做用;函數
④原型對象帶來的一些須要注意的問題;post
沒理解的能夠再複習一下。 傳送門:JS基礎—原型對象的那些事(一)ui
今天講一下原型鏈以及原型鏈的關係圖。this
每一個對象都有一個__proto__
屬性,指向對象的原型。spa
ps:準確的說,是每個實例都有一個[[Prototype]]
屬性,指向原型對象。這是一個隱式屬性,存在可是咱們的腳本訪問不到,不過瀏覽器廠商大部分都支持一個__proto__
屬性,用來顯示指向原型,雖然能用,但__proto__
不是ECMA中的規範。prototype
原型的值能夠是一個對象,也能夠是null
。若是它的值是一個對象,那麼這個對象也必定有本身的原型。這樣就造成了一條線性的鏈,咱們稱之爲原型鏈。3d
當咱們在對象上調用一個屬性或者方法時,會先在這個對象上尋找,沒有的話就去它的原型對象上找,原型對象上沒有就去原型對象的原型對象上找,一直找到原型對象爲null
爲止,沒有的話就是undefined
。
簡而言之,對象尋找一個屬性會沿着原型鏈向上尋找,直到原型鏈的頂端。
仍是以上一篇的Person
爲例
function Person(name) {
this.name = name
}
Person.prototype.sayName = function() {
console.log(this.name)
}
var person = new Person("張三")
複製代碼
咱們先來畫一個簡單的關於原型的關係圖
以上是實例、構造函數和原型對象三者的關係圖。
PS: prototype
只是構造函數上的一個屬性,它是一個指針,指向原型對象,並不表示Person.prototype就是原型對象。這裏將Person.prototype
認爲是原型對象,是爲了方便理解,須要注意哦。
看不懂的同窗去複習上一篇的內容,看懂的咱們繼續。
原型對象也是對象,是對象就有
__proto__
屬性,指向它的原型對象。
在上一個例子中,Person.prototype
就是一個對象,這個對象能夠說是原生Object
構造函數的實例,因此
Person.prototype.__proto__ === Object.prototype
Object.prototype
也是一個對象,因此它也有__proto__
屬性,不過它的__proto__
指向null
,也就是原型鏈的頂端,再往上就沒有了。
從新補充一下關係圖
看懂的咱們繼續
任何函數均可以說是原生
Function
構造函數的實例。
因此Person
構造函數是Function
構造函數的實例。
Person.__proto__ === Function.prototype
複製代碼
繼續我完善咱們的關係圖
可能有人疑惑,Person
不是函數嗎,函數怎麼也有__proto__
,函數不是隻有prototype
嗎?
由於函數本質也是對象啊,在JS的世界裏,萬物皆對象,因此函數有__proto__
沒毛病。
Function.prototype
也是對象,因此和Person.prototype
同樣,Function.prototype
能夠說是原生Object
構造函數的實例,因此
Function.prototype.__proto__ === Object.prototype
複製代碼
補充咱們的圖(紅色的線)
Function
和Object
都是構造函數,根據第二點任何函數均可以說是原生Function
構造函數的實例,那麼
Function.__proto__ === Function.prototype
Object.__proto__ === Function.prototype
複製代碼
完善咱們的圖(藍色的線),大功告成。
恩,就是這麼神奇,Function
是Function
的實例。。。
以上就是原型鏈的關係圖,將這個圖弄懂,原型對象的知識基本就掌握了。
雖然在真實場景中,這些知識用到的沒這麼複雜,可是掌握了最基礎的知識,未來出現問題時,就能更快的找到問題的緣由。
對於新手而言,原型鏈和做用域鏈常常搞混,this和靜態做用域不知道在場景中怎麼使用,確實是很頭疼的問題,但這也許就是js的魅力所在吧。