再來理一理原型 、原型對象、__proto__之間的關係

經過一個例子來聊今天的內容:bash

function Fun(){}
Fun.prototype.age = 18;

var f = new Fun();
console.log(f.age) // 18;
console.log(Fun.age) // undefined
複製代碼

爲何f.age的結果是18,而Fun.age的結果是undefined?函數

在開始以前,咱們先了解一下原型 、原型對象、__ proto__ 這三個概念。spa

基本概念

原型(prototype):是指函數內部的一個屬性,這個屬性是個指針,指向原型對象。prototype

原型對象(prototype object):是指函數內部的一個對象,這個對象包含屬性和方法是共享的。指針

__ proto__([[prototype]]):是實例對象內部的一個屬性,它指向當前函數/Object類型的原型對象。code

它們之間的關係是:cdn

image

prototype屬性 和 __proto __的注意點

有兩個注意點:對象

  1. 單純的對象只有__proto__屬性,沒有prototype屬性
  2. 函數對象有__proto__ 和prototype屬性
    image

原型、原型對象、__ proto __、原型鏈的關係

它們之間的關係,咱們經過下面的圖來了解。 blog

image

經過上面的圖得出一些結論:原型鏈

  1. 全部的原型對象,都有constructor屬性,指向這個實例的構造函數;

  2. 函數的 prototype 屬性指向了一個對象,這個對象正是調用該構造函數而建立的原型對象

  3. __proto__指向原型鏈上一個節點的原型;

  4. 咱們所說的往原型鏈查找屬性或方法,是指"沿着.__proto __屬性找,而不是"沿着.prototype這個屬性去查找;

  5. __ proto__ 和prototype是徹底不一樣的兩個東西; obj. __proto __ === 函數.prototype; 僅僅是說明,它們共同指向原型對象,僅此而已;

  6. 實例.__ proto__ 是構造函數.prototype,構造函數原型對象.__ proto__ 是Object.prototype;即:

obj.__ proto__  === Fn.prototype
    obj.__ proto__.__proto__ === Fn.prototype.__proto__ === Object.prototype
複製代碼

函數.__ proto__ 是Function.prototype,Object類型. __proto __ 是Function.prototype;即:

Fn.__proto__ === Function.prototype
    Object.__proto__ === Function.prototype
複製代碼

Function類型. __proto__是其自己;即:

Function.__ proto __ === Function.prototype
複製代碼
  1. 原型鏈的頂端是null。

回到最初的問題

咱們再回頭看這個例子:

function Fun(){}
Fun.prototype.age = 18;

var f = new Fun();
console.log(f.age) // 18;
console.log(Fun.age) // undefined
複製代碼

爲何f.age的結果是18,而Fun.age的結果是undefined?

f.age:

由於,f是一個實例對象,f.age沒有值,則會往者f上一個節點的原型,f. __ proto __屬性找,

從上圖看是 Fun.prototype(注意,這是一個原型對象,而不是構造函數的prototype屬性==)

因此找到的結果是18。

Fun.age:

由於Fun是一個函數,這個函數上沒有定義.age屬性,(注意:Fun.prototype上的屬性 != Fun的屬性==),那這個時候,就會往Fun.__proto__屬性上找,

從上圖看是Function.protype(原型對象),也沒有找到,再往上找,直到頂端,而後返回undefined。

這回能明白上面的結果了嗎?

相關文章
相關標籤/搜索