一、前言
????????在深入學(xué)習(xí)JavaScript過程中,有一個(gè)概念是不能不提及的,這個(gè)概念就是“原型”-prototype,這個(gè)概念本身是非常重要的但是恰恰又是最不好理解的,這個(gè)概念的理解會(huì)對(duì)以后的學(xué)習(xí)產(chǎn)生很大的幫助,本篇文章就來(lái)初步去學(xué)習(xí)這個(gè)原型。
二、功能
? ??????返回對(duì)象類型原型的引用。
????????這句話猛的看一下貌似不太理解,那么聰明的你就在心里慢慢地默念10遍,如果還不理解,那么請(qǐng)接下來(lái)跟著我的思路一步一步的走,不用怕啰嗦,花半個(gè)小時(shí)把知識(shí)慢慢吃透,我相信對(duì)你會(huì)有收獲的。
三、格式
? ??????class.prototype
????????tips:有的小伙伴可能會(huì)問我,這個(gè)"class"是什么東東呢?在這里,我先暫且把函數(shù)對(duì)象的名稱叫做類。如果大家有Java知識(shí)的話,都知道Java中有“類”的概念,可是事實(shí)上JavaScript中是沒有“類”的概念的,只有“對(duì)象”的概念,在這里為了說明清楚,我分別寫一段JavaScript和Java代碼,來(lái)對(duì)比一下。


? ??????聰明的你肯定一經(jīng)對(duì)比就明白了,那么原型的格式就是:Person.prototype,這也就是我為什么把prototype的格式定義為:class.prototype的原因了。
????????好了,說了這么多,下面正式進(jìn)入正題。
四、prototype的作用
? ??????在說明prototype作用之前,先來(lái)看一個(gè)例子并思考問題。

????????這個(gè)打印結(jié)果很簡(jiǎn)單,就是“zhangsan” 。如果程序?qū)懙竭@里,如果發(fā)現(xiàn)我們要?jiǎng)?chuàng)建的Person對(duì)象發(fā)現(xiàn)少定義了一個(gè)“age”屬性,那么一般我們常用的做法是這樣的,一種是直接改寫Person構(gòu)造函數(shù),即“function Person(username,age)”,這樣做的好處是確實(shí)方便了,但是會(huì)導(dǎo)致“new Person('zhangsan')”這種創(chuàng)建對(duì)象的代碼又要重新修改,否則我們創(chuàng)建的對(duì)象age的值總是“undefined”;另一種做法是可以動(dòng)態(tài)的為創(chuàng)建好的Person對(duì)象(本例子是p1所指向的對(duì)象)添加一個(gè)age屬性,這樣做確實(shí)也挺方便,但是又會(huì)發(fā)生另外一個(gè)問題,就是,如果我要再去創(chuàng)建一個(gè)p2對(duì)象的時(shí)候(var p2 = new Person()),實(shí)際上這個(gè)p2對(duì)象里面仍然是沒有這個(gè)age屬性的。那么現(xiàn)在能不能想一種辦法,或者是現(xiàn)在就想實(shí)現(xiàn)這么一種功能,當(dāng)我把這個(gè)功能實(shí)現(xiàn)了之后,“Person函數(shù)對(duì)象下面的所有創(chuàng)建的實(shí)例都有這么一個(gè)age屬性?”答案是肯定的,那么實(shí)現(xiàn)的方式就是使用的是:“原型”。
五、問題解決
? ??????現(xiàn)在我們來(lái)看下使用“原型”的方式如何去解決上面的例子問題。

????????咦,真奇怪!為什么就添加了“Person.prototype.age = 30”此句代碼就可以實(shí)現(xiàn)所有的Person的實(shí)例對(duì)象都擁有了age屬性呢?好了,開始劃重點(diǎn),下面的這段話要好好琢磨:
? ??????當(dāng)程序去加載Person函數(shù)對(duì)象的時(shí)候,JS引擎就會(huì)為Person構(gòu)造器去創(chuàng)建Person的原型對(duì)象,它們之間是相互獨(dú)立存在的,這個(gè)Person構(gòu)造器里面就有一個(gè)prototype屬性指向了此原型對(duì)象,同時(shí)原型對(duì)象里面也有一個(gè)叫做constructor屬性指向了構(gòu)造器,當(dāng)Person的一個(gè)實(shí)例對(duì)象去使用一個(gè)不存在的屬性時(shí),會(huì)自動(dòng)到Person構(gòu)造器的原型對(duì)象中去找。參考圖1:
? ??????

? ??????從圖上就很直觀了,Person構(gòu)造器有一個(gè)prototype屬性指向了Person原型對(duì)象,而Person原型對(duì)象有一個(gè)constructor屬性指向Person構(gòu)造器,當(dāng)我們?nèi)?shí)例化一個(gè)Person對(duì)象的時(shí)候,生成的對(duì)象內(nèi)部也會(huì)有一個(gè)叫做prototype的屬性指向了這個(gè)Person構(gòu)造器所對(duì)應(yīng)的原型對(duì)象。當(dāng)我們寫Person.prototype.age = 30
????????這句代碼的時(shí)候,“實(shí)際上是將這個(gè)age屬性添加到了這個(gè)Person構(gòu)造器所指向的Person原型對(duì)象”,
????????那聰明的你現(xiàn)在應(yīng)該有點(diǎn)茅塞頓開了吧,當(dāng)我們?nèi)ピL問p1.age的屬性的時(shí)候,其實(shí)這個(gè)p1的實(shí)例對(duì)象里面并沒有age屬性,只有username屬性,那么為什么仍然可以訪問呢?原因就在于當(dāng)實(shí)例對(duì)象去使用一個(gè)不存在的屬性時(shí),會(huì)自動(dòng)到Person構(gòu)造器的原型對(duì)象中去找,那么這樣的話,也就解決了當(dāng)我們無(wú)論創(chuàng)建多少個(gè)實(shí)例對(duì)象,都會(huì)自動(dòng)到Person構(gòu)造器的原型對(duì)象里面去找屬性了。
? ??????tips:插播一條額外話,看一個(gè)代碼:

? ??????現(xiàn)在再來(lái)分析這個(gè)程序,我們知道,constructor的作用是:返回對(duì)象的構(gòu)造器。那么仔細(xì)分析一下為什么是這樣的?我們的p1對(duì)象里面明明壓根都沒有constructor屬性呀,為什么沒有打印undefined,反而是打印了Person構(gòu)造器呢?原因是這樣的:還是如上面所說,當(dāng)我們的一個(gè)實(shí)例對(duì)象去訪問一個(gè)不存在的屬性的時(shí)候,那么這個(gè)時(shí)候就會(huì)自動(dòng)去Person構(gòu)造器的原型對(duì)象里面去找,通過上面圖可以看出來(lái),Person原型對(duì)象里面有一個(gè)constructor屬性又指向了Person構(gòu)造器。哦哦,天哪,原來(lái)是這樣,這個(gè)時(shí)候就應(yīng)該很清晰了吧。
????????聰明的你,冥冥之中是不是又發(fā)現(xiàn)了一個(gè)很問題呢?前面說到:通過原型的方式添加屬性的時(shí)候,所有的實(shí)例對(duì)象都是可以訪問到這個(gè)屬性的?就以上面的例子為例,我們說,p1、p2對(duì)象的age屬性本身是沒有的,但是是可以訪問的,原因就在于訪問不存在的屬性的時(shí)候,實(shí)際上是可以自動(dòng)去找Person構(gòu)造器所對(duì)應(yīng)的Person原型對(duì)象,那么現(xiàn)在的問題是:當(dāng)p1對(duì)象把a(bǔ)ge屬性的值修改之后,會(huì)影響到p2對(duì)象的age的值嗎?來(lái),看代碼:

????????天哪,神奇呢,怎么會(huì)這樣呢?p1對(duì)象和p2對(duì)象中去訪問age屬性,實(shí)際上都是訪問的是Person構(gòu)造器所指向的Person原型對(duì)象,那么既然p1對(duì)象把a(bǔ)ge的值修改為90,那么理論上說p2對(duì)象再去訪問age屬性,值應(yīng)該也是90才對(duì)嘛,你可能會(huì)說,他們指的是同一份age屬性嘛。哈哈,解釋的貌似是合情合理,可是結(jié)果又不是自己的預(yù)期,其實(shí)這樣解釋應(yīng)該更好理解一點(diǎn),就是:p1.age = 90,相當(dāng)于是為p1對(duì)象動(dòng)態(tài)的添加了一個(gè)age屬性,這個(gè)僅僅是對(duì)p1對(duì)象動(dòng)態(tài)添加的,并沒有真正的去訪問修改Person原型對(duì)象中的age屬性的值,而p2對(duì)象仍然是沒有age屬性的,所以p2.age = 30,仍然是相當(dāng)于是從Person原型對(duì)象里面獲取的值,所以是30,而p1對(duì)象自動(dòng)添加了一個(gè)age屬性,其值是90,所以p1.age的值當(dāng)然是90嘍。
????????哈哈,至此,JavaScript中的prototype就解釋完畢了,這個(gè)需要好好琢磨,祝你成功!
? ? ? ? 對(duì)啦還有,圖片中的水印“頭條號(hào)/HelloWorld小碼農(nóng)”是俺今日頭條的小昵稱哦,也歡迎小伙伴關(guān)注哦。