__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
要不來張圖吧
- 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是被訪問的共享原型對象,打個不恰當的比喻,大家同時用右手搭在別人肩上排成一排的時候,鏈接人與人之間的手和人能一樣麽,缺少一個,還能是鏈條麽,當然不能拉,突然想起來,覺得是不是很像一種數據結構,雖然我不常用,但是感覺哇在這裏見到了呢,是什麽呢?沒錯,是鏈表!
__proto__ 與 prototype