原文鏈接:https://blog.csdn.net/lc237423551/article/details/80010100
1.Javascript中所有的對象都是Object的實例,並繼承Object.prototype的屬性和方法,也就是說,Object.prototype是所有對象的爸爸。(個人感覺搞清楚這一點很重要) 。
在對象創建時,就會有一些預定義的屬性,其中定義函數的時候,這個預定義屬性就是prototype,這個prototype是一個普通的對象。
而定義普通的對象的時候,就會生成一個__proto__,這個__proto__指向的是這個對象的構造函數的prototype.
詳情請看例一:(建議大家用谷歌瀏覽器查看這些對象的屬性);
- function A(a){
- this.a = a;
- }
首先定義一個函數a,如上面所說,函數在被定義的時候就擁有了一個prototype對象。我們來打印看一下
console.log(A.prototype)
瀏覽器的結果:
如上圖,這就是函數a的prototype對象,(記住我們最開始說的,凡是對象都會有一個屬性那就是__proto__)。這個__proto__指向的就是他的構造函數的prototype 而這個函數a的prototype對象的構造函數是誰呢? 沒錯就是開頭說到的Object.prototype。
看如下代碼:
- console.log(A.prototype.__proto__)
- console.log(Object.prototype)
而這兩個的結果如下:
打印出來是同一個東西,也就是說Object.prototype是所有函數的爹,當你聲明一個函數的時候也就是相當於對Object的實例化。這裏可以對比一下new一個實例。
我們也可以用幾個方法來驗證一下:
- console.log(Object.prototype.isPrototypeOf(A))//true
- console.log(A instanceOf Object) //true
函數a的prototype對象的另一個屬性是constructor這個屬性就指向了函數a本身,也就是指向了他自己的構造函數。
2.我們在來用一個實例對象來說明一下原型,代碼如下:
- function B(b){
- this.b = b;
- }
- var b = new B('lc');
當我們聲明一個函數B時就自動創建了prototype對象。而b是構造函數的B的實例,這是候b是一個對象,而我們知道,對象只有__proto__屬性。而這個屬性是指向他的構造函數(B)的prototype屬性。這時候我們來打印一下b
console.log(b)
可以看到b中只有__proto__屬性,而這個屬性是指向他的構造函數的prototype對象的,也就是說
(b.__proto__==B.prototype)答案爲true;
這就是js中的prototype和__proto__的區別。
那麼什麼是原型鏈呢?接着上面的講,我們都知道對象都有一個toString方法。上述的實例化對象b也可以toString,
而實例化對象b本身並沒有toString的方法,那他就會沿着它的__proto__向他的構造函數B的prototype對象去找,而這裏也沒有,那他就會 繼續沿着B.prototype.__proto__向上找。而B.prototype.__proto__指向的就是Object.prototype。
我們打印一下Object.prototype:
這就是原型鏈查找,而則一層一層的鏈接 關係就是原型鏈。