從 __proto__ prototype 說起

先來做個複習,ES5中有有幾種數據類型呢?

  • 5種基本數據類型
    • Undefined
    • Null
    • Boolean
    • Number
    • String
  • 1種複雜數據類型
    • Object

除了基本數據類型,萬物皆對象,記住這個很重要,這體現了js設計的哲學思想,和現實生活事物存在的關係一模一樣。

接觸js也一年有餘了,剛開始看各種概念感覺在記憶,先能上手幹活的感覺也讓自己先用了js起來,回頭來看很多概念你不真正用的有些感悟可能真的很迷糊,就像今天突然問自己__proto__ 是幹嘛的,和它長得很像的prototype又是幹嘛的,爲啥不都用一個,看起來讀起來都那麼像。。。。ok,我儘量把自己所思所想記錄下來,能表達的清晰,哈哈其實我理解能力有限哈哈哈。

不讓自己思維繞彎子,當我們想完全弄清楚一件事情的時候,那麼最好搞清楚我們最關心的兩個問題:它是什麼,有什麼用,那麼先直接給幾個定論(如果有誤區請各位大神指正):

是什麼

  • __proto__ 
    每個對象都擁有的屬性

  • prototype 
    每個方法都擁有的屬性

有什麼用

  • 讓js擁有了原型鏈來達到共享數據和方法的目的

好了,先來說是什麼,那麼讓我們想想幾個關鍵字:每個對象,每個方法,那麼記得開始很重要的一件事兒麼,就是js中萬物皆對象,那麼方法是什麼鬼,沒錯,方法也是對象,一種需要特殊拎出來的對象,特殊在哪呢,那麼牛逼。。。。其實就是要理解是什麼中,方法比對象更牛逼一些,因爲它既是對象又是方法。。。。所以呢?說明方法既有__proto__屬性又有prototype屬性。那麼我們可以開始看例子來加深理解:

var A = function(){}; // A是一個方法,當然也是個對象  
var a = new A(); // a是一個由A創造出的對象,不是方法  

//看一看對象非方法的行爲
console.log(a.__proto__); //object  
console.log(a.prototype); //undefined, 對象沒有 

//看一看方法的行爲,方法也是對象哦

console.log(A.__proto__); //function  
console.log(A.prototype); //object  

是不是有點暈了,哈哈我也是,別急至少我們驗證了我們是什麼的定論,接下來研究下有什麼用,其實在這之前難道不好奇a.__proto__,a.prototype, A.__proto__,A.prototype, 都等於誰嗎?那我們來接着驗證。

console.log(a.__proto__ === A.prototype); //true  
console.log(a.prototype === undefined); //true

console.log(A.__proto__ === Function.prototype); //true  
console.log(A.prototype === a.__proto__); //true  

矣,是不是看出來點神馬?沒錯,有一點點原型鏈的感覺了,那麼繼續

//先看a這條鏈
console.log(a.__proto__.__proto__ === A.prototype.__proto__); //true  
console.log(a.__proto__.__proto__ === Object.prototype);//true  
console.log(a.__proto__.__proto__.__proto__ === Object.prototype.__proto__);//true  
console.log(a.__proto__.__proto__.__proto__ === null);//true


//再看看A這條條鏈
console.log(A.__proto__.__proto__ === Function.prototype.__proto__);//true  
console.log(A.__proto__.__proto__ === Object.prototype);//true  
console.log(A.__proto__.__proto__.__proto__ === Object.prototype.__proto__);//true  
console.log(A.__proto__.__proto__.__proto__ === null);//true  

矣,像不像兩個鏈條了?而且這兩個鏈條還有些關係呢,頭大?我也是。。要不來張圖吧

說明一下,這裏有兩類事物:對象和對象方法,對象方法是我起的名字。。。哈哈,記住方法也是對象,js萬物皆對象哦。其中紅色框是表示的原型對象,網上很多圖把它和擁有它的對象畫在一起,我覺得不夠直觀,所以就自己畫出來啦,對照上面總結的是什麼和原型鏈的驗證,再配合這張圖,箇中體會,哈哈有木有豁然開朗的趕腳,如果沒有不要緊,多看幾遍嘍哈哈哈

然後我們來看下,這張圖幾個有意思的地方。

  • 首先看a對象,有三種不同方式創建的a對象,它們的原型鏈指向是不同的哦,體會一下,是不是還是很合情合理。
  • Function的__proto__指向的是自己即Function的prototype,而Function的prototype的__proto__指向的是Object的prototype,而Object的__proto__指向了Function的prototype,what????沒錯,看圖,它們形成了一個環狀引用。。。所以知道爲什麼說方法也是對象了吧,看到沒,萬物歸終,最後都指向了Object, 而Object的原型鏈又指向誰了呢,一個大大的null,哈沒錯,null是到頭了,空也是終極對象啊,看到js的哲學了麼,其實萬物皆空,善哉善哉。。。
  • 最後來解決文章剛開始提出的問題,__proto__和prototype爲啥會有兩個,用一個不行嘛,看了圖或許我們能參悟到了吧
    • __proto__纔是原型鏈, 除了第三種方式創建的對象和Object的終極指向,它始終指向prototype
    • prototype是一個原型對象,其中包含的屬性(用戶自我添加的)就是我們總結的有什麼用中提到的,就是包含共享的數據和方法的對象
    • 至於爲什麼有兩個,很簡單,兩個人乾的事兒不一樣,不能互相代替,__proto__是指向共享原型對象的訪問句柄,而prototype是被訪問的共享原型對象,打個不恰當的比喻,大家同時用右手搭在別人肩上排成一排的時候,鏈接人與人之間的手和人能一樣麼,缺少一個,還能是鏈條麼,當然不能拉,突然想起來,覺得是不是很像一種數據結構,雖然我不常用,但是感覺哇在這裏見到了呢,是什麼呢?沒錯,是鏈表!

這個js原型鏈系列的文章還會繼續完善,希望自我總結,也希望讀到的人能有所幫助,也更希望各位大神多多指點~

發佈了71 篇原創文章 · 獲贊 72 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章