1. 程式人生 > >對`prototype`和`__proto__`的理解

對`prototype`和`__proto__`的理解

談談對prototype__proto__的理解

之前初學JavaScript的時候,被這兩個東西搞得迷迷糊糊的,前兩天看JS高程的時候,看到了prototype,自己好好的總結了一下

1. 建構函式,原型物件,例項

建構函式的原型屬性 prototype指向了原型物件,在原型物件有的屬性和方法,建構函式構造出的例項都可以繼承共享,不是很恰當的說,如果建構函式是例項的爹,那麼原型物件就是建構函式的爹,也就是例項爹的爹,爺爺。

建構函式是函式

原型物件的物件

例項也是是物件

以下列程式碼為例:

function Foo () {}
foo = new Foo ()

上面程式碼創造了一個建構函式,並new了一個Foo的例項foo,我們可以在控制檯列印下面程式碼

1536647396354

可以很明顯看到,Foo建構函式是一個function,而foo例項和Foo.prototype原型物件都是物件

2. 關係示意圖

3. 詳解

prototype 是屬於一個函式特有的屬性,而 __proto__一般存在於物件之中

  • Foo函式作為一個建構函式,它的的prototype指向它的原型,Foo.prototype是一個物件,裡面的屬性和方法能傳給Foo構造的例項之中。

  • 而Foo.prototype這的物件有一個屬性 為 constructor (構造器屬性),constructor屬性指向原型物件對應的建構函式,也就是指向 Foo foo.constructor --> ƒ Foo() {}

  • 物件具有__proto__ 可稱為隱式原型,一個物件的隱式原型,指向構造改物件(foo)的建構函式(Foo)的原型(Foo.prototype),這也保證了例項能夠訪問繼承建構函式原型物件中的屬性和方法

    所以,foo.__porto__ === Foo.prototype

  • 物件沒有prototype屬性,所以 foo.prototype = undefined

  • 但是函式可以有__proto__屬性,因為函式的本質也是一個物件

    Foo是一個方法,既一個函式,函式本身也是一個特殊的物件,把Foo作為一個物件來看,它的__proto__指向Foo建構函式本身的建構函式的原型,Foo建構函式的建構函式是是Function

    Foo.constructor --> ƒ Function() { [native code] } (後者即是Function)

    Foo.constructor === Function // true

    Foo.constructor.prototype === Foo.__proto__ // true

    Function.prototype === Foo.__proto__ // true

  • 原型物件是物件,也有__proto__屬性,我們可以在控制檯列印 Foo.prototype.__proto__發現出現了一個物件,裡面有很多屬性 包括 constructor, hasOwnProperty, isPrototypeOf,等等的方法

    其實這個物件就是Object.prototype, 而Object就是這個原型物件的建構函式

    這裡的Object是一個建構函式,不是一個物件,不要搞錯,typeof(Object) --> function

  • 最後我們看一下Object.prototype這個物件的__proto__屬性,我們會發現為Null

    Object.prototype.__proto__ // null

  • Function.prototype === Function.__proto__ // true

    Function的原型和Function的__proto__竟然全等,構造Function的建構函式的原型 等於 Function的原型

    我們發現一個有趣的東西 Function 是由 Function 構造的 ,Function可以看成是呼叫其自身的new操作的例項化的結果,哈哈 有點意思,沒爹,自己把自己搞出來了。。

    我們接著試探,發現Function.prototype當做一個物件來看,他的建構函式是Object( )函式,那麼Function.prototype.__proto也就是Object的原型了

    所以 Function.prototype.__proto__ ===Object.prototype // true

4. 總結

  • 物件有屬性__proto__,指向該物件的建構函式的原型物件
  • 方法除了有屬性__proto__,還有屬性prototype,prototype指向該方法的原型物件
  • 函式(Function也是函式)是new Function的結果,所以函式可以作為例項物件,其建構函式是Function(),原型物件是Function.prototype
  • 物件(函式也是物件)是new Object的結果,所以物件可以作為例項物件,其建構函式是Object(),原型物件是Object.prototype
  • Object.prototype的原型物件是null