【JS基礎】原型物件的那些事(二)

諾頓發表於2019-05-05

上一篇講了

①原型物件是什麼;

__proto__prototypeconstructor的關係;

③原型物件的作用;

④原型物件帶來的一些需要注意的問題;

沒理解的可以再複習一下。 傳送門:JS基礎—原型物件的那些事(一)

今天講一下原型鏈以及原型鏈的關係圖。

原型鏈是什麼

每個物件都有一個__proto__屬性,指向物件的原型。

ps:準確的說,是每一個例項都有一個[[Prototype]]屬性,指向原型物件。這是一個隱式屬性,存在但是我們的指令碼訪問不到,不過瀏覽器廠商大部分都支援一個__proto__屬性,用來顯示指向原型,雖然能用,但__proto__不是ECMA中的規範。

原型的值可以是一個物件,也可以是null。如果它的值是一個物件,那麼這個物件也一定有自己的原型。這樣就形成了一條線性的鏈,我們稱之為原型鏈

當我們在物件上呼叫一個屬性或者方法時,會先在這個物件上尋找,沒有的話就去它的原型物件上找,原型物件上沒有就去原型物件的原型物件上找,一直找到原型物件為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
複製程式碼

補充我們的圖(紅色的線)

圖片描述

注意點四

FunctionObject都是建構函式,根據第二點任何函式都可以說是原生Function建構函式的例項,那麼

    Function.__proto__ === Function.prototype
    
    Object.__proto__ === Function.prototype
複製程式碼

完善我們的圖(藍色的線),大功告成。

圖片描述

恩,就是這麼神奇,FunctionFunction的例項。。。

以上就是原型鏈的關係圖,將這個圖弄懂,原型物件的知識基本就掌握了。

雖然在真實場景中,這些知識用到的沒這麼複雜,但是掌握了最基礎的知識,將來出現問題時,就能更快的找到問題的原因。

對於新手而言,原型鏈和作用域鏈經常搞混,this和靜態作用域不知道在場景中怎麼使用,確實是很頭疼的問題,但這也許就是js的魅力所在吧。

相關文章