關於原型鏈的問題也是領悟了好久,有時候忽然以爲什麼都懂了,但下一個問題出現使人一臉蒙比,好像又什麼都不懂,這是最近的一點經驗,記下來方便之後複習。函數
先貼上最經典的原型鏈圖,說實話,這圖是真的很精髓了this
首先咱們要知道這句話: js中全部的東西(固然都是對象)都有__proto__,全部的函數除了有__proto__,還有prototype;spa
而後咱們要區分這兩個東西,__proto__和prototype.prototype
1. __proto__,起初我不明白爲何全部的名字都是英文的,這個非得要弄幾個槓。如今終於以爲這是很是形象的,由於__proto__表明着指針,下面咱們統一把這個叫原型指針(本身叫的,也不知道有沒有官方叫法),它的含義很明顯了,這個屬性是指向某個東西,就是構造函數的原型對象,實際上也就是那個原型對象在堆空間裏的內存地址指針
2. prototype,他纔是所謂的函數的原型對象,他確定含有的兩個屬性。1 constructor,表明這個東西是哪一個函數的原型對象;2,他也是對象,確定也有原型指針;code
反正我開始的理解難點是在這裏:子類不是繼承來自父類的原型嗎。那這個子類的指針__proto__直接就指向父類(構造函數),這樣一級級找上去不久行了?這不是很符合他來自於父類嗎?咱們看一下,這樣找到Funtion(就是途中第三個boss,我叫它大function)的時候,它的原型指針應該指向誰呢?明顯沒有了,由於他就是全部函數的爸爸,沒有比它更高級的構造函數了。因此這種是行不通的。哦,這個也有解決辦法,那咱們也讓這個大function的指針指向null。可是這樣作會有很大的缺點,咱們在接下來js採用的方法會說到對象
js採用了另外一種辦法,咱們給每一個構造函數(全部的函數均可以叫構造函數)都定義一個prototype屬性。讓子類的這個指針不是指向構造函數,而是指向構造函數的prototype(原型對象),這個對象中的constuctor屬性反過來指向這個函數自己,而後它的原型指針天然也要指向它的構造函數的原型對象,像這樣一個對象的構造函數是誰呢。就是咱們的Object(大object)。開闢了一個新屬性prototype有一個很大的好處就是,咱們能夠把構造函數想共享給全部子類的那部分屬性、方法和不能共享的那部分隔離開,由於每一個實例對象總有些東西是本身特有的,每一個實例都不同,好比名字(私有屬性),這種就直接在構造函數裏用this.name 定義。只把須要共享,傳承下去的那部分放在prtotype原型對象裏面就行了。blog
下面咱們一個對比的代碼就能明白那些共享部分是怎麼繼承的了繼承
1 //先肯定一下角色。Father是本身的構造函數,child是它的一個實例 2 function Father(){}; 3 var child= new Father; 4 child.__proto__ == Father.prototype; 5 child.__proto__.__proto__ == Father.prototype.__proto__ == Object.prototype 6 child.__proto__.__proto__.__proto__ ==Father.prototype.__proto__.__proto__ == Object.prototype.__proto__ == null 7 //就經過__proto__指針鏈不斷的訪問到上一級原型對象裏共享的方法 8 //本身封裝的構造函數裏 咱們也能夠加入要分享的方法,只須要加到Father的 9 //原型對象prototype,那全部的子類就能夠訪問到了 10 Father.prototype.say=function(){console.log('hello world')}