先看一個(gè)典型的單向鏈表
上面這段代碼,是一個(gè)典型的單向鏈表
我們只能通過n.next來找到下一個(gè)節(jié)點(diǎn)
但是沒有辦法從當(dāng)前節(jié)點(diǎn)找到上一個(gè)節(jié)點(diǎn)
不過這和原型鏈有什么關(guān)系呢?
目前還沒有關(guān)系。
原型對(duì)象從哪來?
分析上面這段代碼
為什么obj明明是空的,卻還能調(diào)用toString方法?
這toString方法是哪里來的呢?
再比如我們的數(shù)組對(duì)象
其實(shí),這些方法都來自于一個(gè)叫做原型的家伙
我們可以使用 對(duì)象.__proto__ 的形式把原型對(duì)象打印出來
這是所有對(duì)象的一個(gè)隱式屬性, 也就是正常情況下打印對(duì)象, 我們是看不到這個(gè)屬性的
但我們依然可以通過__proto__ 這樣一個(gè)比較奇怪的屬性名字來訪問原型對(duì)象
這個(gè)屬性名稱訪問起來確實(shí)不夠方便,實(shí)際上它還有另外一種訪問方式
也是一種比較正式的訪問方式, 就是通過函數(shù)名來訪問
例如看下面這個(gè)例子
現(xiàn)在我們大概有了一些疑問
· 1.原型對(duì)象中的所有屬性,實(shí)例對(duì)象都能隨便訪問嗎?
· 2.每個(gè)實(shí)例對(duì)象都有自己的原型對(duì)象, 還是大家共用一個(gè)?
· 3.實(shí)例對(duì)象自己的屬性和原型的屬性沖突了, 會(huì)訪問誰呢?
· 4.原型對(duì)象跟繼承有什么關(guān)系?
· 5.原型鏈又是怎么來的?
我們依次來解決這幾個(gè)疑問
· 原型對(duì)象中的所有屬性,實(shí)例對(duì)象都能隨便訪問嗎?
廢話不多說, 我們來試驗(yàn)一下, 就知道結(jié)果
在上面的代碼中,我們創(chuàng)建一個(gè)構(gòu)造函數(shù) Phone
同時(shí)我們給原型對(duì)象,添加了 price、color兩個(gè)屬性
同時(shí)添加了 playmusic、phonecall兩個(gè)方法
接下來我們通過實(shí)例對(duì)象來訪問一下這些內(nèi)容
可以看到,原型中的屬性和方法都可以被實(shí)例對(duì)象直接訪問!
· 每個(gè)實(shí)例對(duì)象都有自己的原型對(duì)象, 還是大家共用一個(gè)?
這是一道非常簡(jiǎn)單的數(shù)學(xué)證明題,證明過程如下:
最終結(jié)論是, 所有實(shí)例對(duì)象共享同一個(gè)原型對(duì)象
· 實(shí)例對(duì)象自己的屬性和原型的屬性沖突了, 會(huì)訪問誰呢?
我們?cè)賮碓囼?yàn)一下
可以看到, 如果對(duì)象本身存在這個(gè)屬性或方法, 會(huì)優(yōu)先訪問自己的
如果沒有, 則訪問原型的屬性, 訪問過程如下圖
· 原型對(duì)象跟繼承有什么關(guān)系呢 ?
請(qǐng)你再思考一個(gè)問題
如果原型也是一個(gè)對(duì)象
那么它必然也應(yīng)該有自己的原型對(duì)象,不是嗎?
我們可以通過 p1.__proto__.__proto__ 進(jìn)行訪問
我們把圖畫的再簡(jiǎn)單一點(diǎn)
從圖中可以看出,只要原型對(duì)象一直存在
對(duì)象P1就擁有了所有原型對(duì)象的能力, 我們也管這個(gè)叫做 繼承
而這些原型對(duì)象之間是什么關(guān)系呢?
p1
p1.__proto__
p1.__proto__.__proto__
p1.__proto__.__proto__.__proto__
原型鏈, 因此而得名
需要補(bǔ)充的問題
原型對(duì)象真的沒有盡頭嗎?
當(dāng)然不是的, 原型對(duì)象由瀏覽器自動(dòng)創(chuàng)建, 當(dāng)然也有它自己的規(guī)則
規(guī)則如下:
1.每個(gè)構(gòu)造函數(shù)在誕生的時(shí)候, 都會(huì)創(chuàng)建一個(gè)該函數(shù)的實(shí)例對(duì)象作為默認(rèn)原型
相當(dāng)于 Phone.prototype = new Phone();
2.而這個(gè)原型對(duì)象的原型, 則默認(rèn)指向Object.prototype
相當(dāng)于 Phone.prototype.__proto__ = Object.prototype;
3.當(dāng)然, Object.prototype 也是它自己的實(shí)例
相當(dāng)于 Object.prototype = new Object();
4. 但是, Object.prototype不再擁有原型對(duì)象
相當(dāng)于 Object.prototype.__proto__ = null
5. 因此,原型對(duì)象是有上限的
p1.__proto__ 可訪問
p1.__proto__.__proto__ 可訪問
p1.__proto__.__proto__.__proto__ 為null
原型的最重要的作用就是擴(kuò)展能力