JavaScript學習筆記之constructor,prototype,__proto__解惑

boborz發表於2017-12-20

引言

在學習JavaScript時,不可避免的接觸到了原型原型鏈的概念,結果被constructorprototype__proto__這些屬性搞得一臉懵逼,這些都是什麼鬼!!!通過谷歌瀏覽器除錯時,看物件例項的內部結構,這三個屬性也是你中有我,密不可分,完全理不清頭緒。最後通過理清概念,不斷驗證,最終有了一些思路。

概念

要想真正弄清楚constructorprototype__proto__這些屬性的之間的區別和聯絡,首先我們要明確定義:

  • constructor屬性始終指向建立當前物件的建構函式
  • prototype屬性是每個函式物件都具有的屬性,被稱為原型物件,因為其本身也是個物件。
  • __proto__屬性是每個物件具有的屬性。一旦原型物件被賦予屬性和方法,那麼由相應的建構函式建立的例項物件會繼承prototype上的屬性和方法。

事例

下表列出了例項物件和函式物件的區別:

constructor prototype __proto__
A ✔︎ ✔︎ ✔︎
a ✔︎ ✔︎

由上表可以看出例項物件是沒有prototype屬性的,只有函式物件才有(這一點很重要!!!),下面用程式碼來具體解釋下以上三個屬性的關係:

<script type="text/javascript">
    function A() {};
   
    var a = new A();
</script>
複製程式碼

JavaScript實際上執行的是:

<script type="text/javascript">
    function A() {};

    var a = new Object();
    a.__proto__ = A.prototype;
    A.call(a);
</script>
複製程式碼

其中A.prototype也是個物件,它由constructor__proto__屬性組成 (這一點很重要!!!),它的構造過程如下:

A.prototype = new Object();
A.prototype.constructor = A;
A.prototype.__proto__ = Object.prototype;
複製程式碼

ObjectFunction原型物件

  • JavaScript中的所有物件都來自Object,所有物件從Object.prototype繼承方法和屬性,儘管它們可能被覆蓋。例如,其他建構函式的原型將覆蓋constructor屬性並提供自己的toString()方法。Object原型物件的更改將傳播到所有物件,除非受到這些更改的屬性和方法沿原型鏈進一步覆蓋。它的構造過程如下:

    Object.prototype = new Object();
    Object.prototype.constructor = Object;
    Object.prototype.__proto__ = null;
    
    ...
    
    Object.__proto__ = Function.prototype;
    複製程式碼
  • 全域性的Function物件沒有自己的屬性和方法, 但是, 因為它本身也是函式,所以它也會通過原型鏈從Function.prototype上繼承部分屬性和方法。Function例項從Function.prototype 繼承了一些屬性和方法。 同其他建構函式一樣, 你可以改變建構函式的原型從而使得所有的Function例項的屬性和方法發生改變。它的構造過程如下:

    Function.prototype = new Function();
    Function.prototype.constructor = Function;
    Function.prototype.__proto__ = Object.prototype;
    
    ...
    
    Function.__proto__ = Function.prototype;
    複製程式碼

驗證

我們通過谷歌瀏覽器來進行除錯,來驗證我們的結論,先來看下Object原型物件,如下圖:

JavaScript學習筆記之constructor,prototype,__proto__解惑

再來看下Function原型物件,如下圖:

JavaScript學習筆記之constructor,prototype,__proto__解惑

最後看下a_a例項物件,如下圖:

測試程式碼

JavaScript學習筆記之constructor,prototype,__proto__解惑

紅框框住的部分就是所謂的原型鏈,原型鏈中的方法,例項物件a_a都可以訪問,JavaScript也是用原型鏈來實現繼承的。

另外,還有一件有趣的事情,如下圖:

無限遞迴

可以無限延展下去,是不是很有趣,有興趣的同學可以試一下,可以加深你對這三個屬性的理解,哈哈?。

結語

關於怎麼用原型和原型鏈來實現繼承,網上有很多好的博文供大家參考,大家也可以參考以下連結,我在這裡就不再廢話了。本文如有錯誤,希望指正,不勝感激!

參考連結

segmentfault.com/a/119000000…
segmentfault.com/a/119000000…
blog.jobbole.com/9648/

相關文章