天天看點

Js中prototype、[[prototype]]和__proto__的差別和用法

一.顯式原型&隐式原型

顯式原型:

prototype

隐式原型:

__proto__

1.1 Important
  • __proto__

    是每個對象都具有的屬性
  • prototype

    Function

    獨有的屬性
1.2 Tips
  • 對象的隐式原型的值為其對應構造函數的顯式原型的值
    • fn.__proto__ === Function.prototype

  • 函數的

    prototype

    屬性是定義時自動添加的。預設為

    {}

  • 對象的

    __proto__

    屬性是建立對象時自動添加的,預設值為其構造函數的

    prototype

  • Object.prototype.__proto__ === null

1.3 說了這麼多和

[[prototype]]

有什麼關系?

其實

[[prototype]]

__proto__

意義相同,均表示對象的内部屬性,其值指向對象原型。前者在一些書籍、規範中表示一個對象的原型屬性,後者則是在浏覽器實作中指向對象原型。

二.作用

作用方面來講當然是實作繼承了。其中最經典的共享屬性方法的原型鍊繼承。其中必不可少的屬性就是

__protoo__

prototype

我們舉個栗子

function Son(){}
function Father(){}
Son.prototype = new Father();
           

如此即實作了繼承

我們可以寫代碼進行驗證

符合上述第三條規則,是以可以通過此方法完成函數的繼承。

注意,此為原型鍊繼承,其中的方法魚屬性為此鍊上的所有執行個體所共享

三.教你手撸原型鍊

原型鍊無非就是一堆繼承關系:

  • 我們隻需要将兒子原型的

    __proto__

    屬性指向父親的

    prototype

    屬性,構造函數的

    prototype

    屬性的

    constructor

    屬性指向其本身即可。
  • 不過需要注意的一點是,已經被執行個體化的對象

    __proto__

    屬性指向其構造函數的

    prototype

  • 另外一個特殊的對象

    Object

    。作為所有對象的父類他的原型的

    __proto__

    屬性指向

    null

Js中prototype、[[prototype]]和__proto__的差別和用法

如此我們就可以看得懂那張經典的原型鍊圖解啦

四.從原理讨論原型鍊的用處

4.1 typeof

typeof

作為《JavaScript進階程式設計》中首推的判斷類型方法無疑是大多數人的選擇。不過令人煩惱的是我們發現當碰到

Array

Function

等類型時他均傳回一個

Object

。這就有點氣人了。是以機智的玩家們采取了

Object.prototype.toString.call(obj)

方法來識别對象類型。他會傳回一個

"[object Type]"

的東西來告訴你所指對象的類型。

此處就用到了原型鍊必不可少的

prototype

。通過改變

this

指針指向将我們所要驗證類型的對象。以完成類型的檢驗

4.2 instanceof

除去

typeof

外我們還有另一個方法:

instanceof

看過我之前轉載的關于typeof與instanceof原理的好兄弟估計會猜到我要說什麼,不過我還是要繼續BB。

instanceof

這個方法用于判斷某執行個體是否從屬于某種類型,同時也可以判斷一個執行個體是否是其父類型或者祖先類型的執行個體。舉個栗子

function Son(){}
function Father(){}
Son.prototype = new Father();

var son = new Son();
son instanceof Son  //true
son instanceof Father  //true
           

看見沒,隻要你是這一家子的人(執行個體)那你無論走哪這祖宗祠堂(原型鍊上的老東西們)都認你。那麼他們是如何判斷你是不是這家的兒孫呢?當然是原型鍊。我們來試着寫一串僞代碼來進行驗證

function new_instance_of(leftVaule, rightVaule) { 
    let rightProto = rightVaule.prototype; // 取右表達式的 prototype 值
    leftVaule = leftVaule.__proto__; // 取左表達式的__proto__值
    while (true) {
    	if (leftVaule === null) {
            return false;	
        }
        if (leftVaule === rightProto) {
            return true;	
        } 
        leftVaule = leftVaule.__proto__ 
    }
}
           

如此這般,通過原型鍊認祖歸宗。咱們看看是否有用

new_instance_of(son, Son)	// true
new_instance_of(son, Father)	// true
           

今天的内容就這麼多

Js中prototype、[[prototype]]和__proto__的差別和用法

繼續閱讀