深入了解javascript(三)——面向?qū)ο笈c原型

面向?qū)ο笫莏s最難弄懂的一部分,我在看了《Javascript高級程序設(shè)計》之后還看了李炎恢老師關(guān)于面向?qū)ο笈c原型的講解购笆,算是理解了粗悯,在此做下筆記,僅為以后的個人學習作參考同欠。先從創(chuàng)建對象逐步剖析

Object構(gòu)造函數(shù)創(chuàng)建多個實例

這種Object構(gòu)造函數(shù)創(chuàng)建多個對象样傍,容易造成代碼冗余,所以有工廠模式的出現(xiàn)

工廠模式創(chuàng)建對象行您,就是普通函數(shù)的創(chuàng)建

但是工廠模式?jīng)]有解決多個對象識別的問題铭乾,即怎樣知道一個對象的類型,怎樣體現(xiàn)呢

工廠模式無法解決對象識別的問題

很明顯娃循,box2是createObject的對象炕檩,但三個提示框的結(jié)果都是true,只知道它們都是object捌斧,但不知道是誰的對象笛质,所以就有了構(gòu)造函數(shù)創(chuàng)建對象模式的出現(xiàn)

構(gòu)造函數(shù)很好地接解決了工廠模式無法識別對象的類型的問題


注意幾點: 構(gòu)造函數(shù)沒有顯式地創(chuàng)建對象;直接將屬性和方法賦給了this對象捞蚂;要創(chuàng)建實例妇押,必須使用new 關(guān)鍵字;將構(gòu)造函數(shù)的作用域直接付給這個對象(this也就指向了這個新對象)姓迅;構(gòu)造函數(shù)的首字母必須大寫敲霍,比如例子中的Box,Box1丁存;

構(gòu)造函數(shù)的調(diào)用

構(gòu)造函數(shù)的問題(不同實例的同名函數(shù)不相等)

創(chuàng)建兩個完成同樣任務(wù)的函數(shù)沒有必要肩杈,但我們可以這樣來解決

我們把sayName()函數(shù)的定義轉(zhuǎn)移到構(gòu)造函數(shù)外部,在構(gòu)造函數(shù)內(nèi)容解寝,我們把sayName屬性設(shè)置成等于全局的sayName函數(shù)扩然,box1、box2對象就共享了在全局作用中定義的同一個sayName函數(shù)聋伦,這著實解決了兩個函數(shù)做同一個事情夫偶。但是新的問題又來了,sayName是全局函數(shù)觉增,如果對象需要用到多個函數(shù)兵拢,那么就要定義多個全局函數(shù),這樣這個自定義的引用類型沒有封裝性可言逾礁。我們可以通過原型模式來解決

使用原型的好處:讓所有對象實例共享它的屬性和方法

理解原型對象:只要創(chuàng)建了一個新的函數(shù)说铃,就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個prototype屬性,這個屬性指向原型對象。在所有默認的請款下截汪,所有的原型對象都會自動獲得一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含一個指向prototype屬性所在函數(shù)的指針植捎。就拿上面的例子來說衙解,Box.prototype.constructor指向Box

這張圖是《Javascript高級程序設(shè)計》上面,實例對象和屬性方法的名字不一樣而已焰枢,蚓峦、
紅線標注的返回true

用原型對象isPrototype()方法測試了Box,因為它們的內(nèi)容都有一個Box.prototype的指針济锄,因此都返回了ture

每當代碼讀取某個對象的某個屬性時暑椰,都會從實例開始,如果找到了話就返回荐绝,沒有找到則繼續(xù)搜索指針指向的原型對象一汽,在原型對象中查找具有給定名字的屬性。

可以通過對象實例訪問原型的值低滩,但是不能通過對象實例重寫原型中的值召夹,但是可以通過delete完全刪除實例屬性的值,從而使對象實例訪問原型的值

通過delete刪除實例屬性


hasOwnProperty()可以檢測一個屬性是存在實例中還是存在原型中恕沫,存在實例中返回true

原型與in操作符(兩種使用情況:單獨使用和在for-in循環(huán)當中)

還有個值得注意的是hasprototypeProoerty()是與hasOwnprotery剛好相反

使用字面量來創(chuàng)建原型

原型的動態(tài)性


關(guān)于這里我是有個問題的监憎,難道說原型要寫在創(chuàng)建實例對象之前,才不會說是切斷實例與原型的關(guān)系

原型對象的問題:也是原型對象的優(yōu)點婶溯,即最大的問題是由共享屬性所導致的鲸阔。然而,如果原型當中包含引用類型的屬性來說迄委,問題就比較突出了

這里還是有個問題

兩張圖的區(qū)別是一個通過box1.family.push()褐筛,另一張是通過box1.family = [],結(jié)果不一樣,引用類型.屬性.方法可以重寫原型當中的值跑筝,但是引用類型.屬性只能操作但是不能修改原型中的值死讹,針對這些問題,所以有組合使用構(gòu)造函數(shù)和原型模式的出現(xiàn)

組合使用構(gòu)造函數(shù)和原型模式

構(gòu)造函數(shù)+原型實在ECMAScript當中最廣泛曲梗、認同度最高的一種創(chuàng)建定義類型的方法

動態(tài)原型模式


紅線標注的部分說明在run()方法不存在的情況下執(zhí)行

注意:使用動態(tài)原型模式赞警,不能使用對象字面量重寫原型;如果在創(chuàng)建實例的情況下虏两,那么就會切斷現(xiàn)有實例與原型之間的關(guān)系

寄生構(gòu)造函數(shù)模式

?

改函數(shù)的作用是僅僅是封裝創(chuàng)建對象的代碼愧旦,然后在返回新創(chuàng)建的對象。關(guān)于寄生構(gòu)造函數(shù)模式:返回的對象與構(gòu)造函數(shù)或者構(gòu)造函數(shù)的原型屬性之間沒有關(guān)系定罢;也就是說笤虫,構(gòu)造函數(shù)返回的對象與在構(gòu)造函數(shù)外部創(chuàng)建的蚃沒有什么不同。為此,不能依賴instanceof操作符來確定對象類型琼蚯。不建議使用這種模式

穩(wěn)妥構(gòu)造函數(shù)模式

咋一看酬凳,好像跟寄生構(gòu)造函數(shù)沒有什么不同。但還是有兩點不同的遭庶,一是新建對象的實例方法不引用this宁仔;二是不使用new操作符調(diào)用構(gòu)造函數(shù),Box里面的屬性是似有峦睡,除了run方法之外翎苫,沒有其他的辦法訪問name和age屬性,因此穩(wěn)妥構(gòu)造函數(shù)是比較安全的


繼承

繼承是OO(面向?qū)ο螅┱Z言一個重要的概念榨了。許多OO語言都支持兩種繼承方式:接口繼承和實現(xiàn)繼承煎谍。接口繼承則繼承方法簽名,函數(shù)沒有簽名龙屉,因為ECMAScript只支持實現(xiàn)繼承呐粘,而且實現(xiàn)繼承主要是依靠原型鏈來實現(xiàn)的

原型鏈:利用一個引用類型繼承另一個引用類型的屬性和方法。構(gòu)造函數(shù)叔扼、原型和實例的關(guān)系:每個夠走啊函數(shù)都有一個原型獨享事哭,原型對象都包含一個指向構(gòu)造函數(shù)的指針,而實例都柏寒一個指向原型對象的內(nèi)部指針瓜富。

原型鏈繼承

注意:有時我們需要在子類型中重寫超類型的某個方法鳍咱,或者需要添加超類型中不存在的某個方法,但不管怎樣与柑,給原型添加方法的代碼一定要在替換原型之后

還有一點谤辜,通過原型實現(xiàn)繼承時,不能使用對象字面量創(chuàng)建原型方法价捧,因為這樣會重寫原型鏈

原型鏈的問題:1丑念、包含引用類型值得原型屬性會被實例共享(之前的解決辦法是使用構(gòu)造函數(shù)+原型,即引用類型值放在構(gòu)造函數(shù)當中而不是原型當中)结蟋,通過原型鏈繼承脯倚,被繼承的原型會成為繼承的原型的一個實例,進而原先的實例屬性會成為另外一個原型的實例屬性了)

2嵌屎、在創(chuàng)建子類型的實例時推正,不能像超類型的構(gòu)造函數(shù)中傳遞參數(shù)

借用構(gòu)造函數(shù)實現(xiàn)繼承

解決了單獨使用原型鏈的兩個問題:借用構(gòu)造函數(shù)引起引用類型沒有被共享同時還解決了子類型向超類型傳參的問題

借用構(gòu)造函數(shù)的問題:方法都在構(gòu)造函數(shù)當中定義,函數(shù)復(fù)用就無從談起了宝惰。而且植榕,在超類型的原型中定義的方法,對子類型而言是不可見的

推薦:組合繼承(原型鏈+構(gòu)造函數(shù))

組合繼承避免了原型鏈和構(gòu)造函數(shù)的缺陷尼夺,融合了它們的優(yōu)點

原型式繼承尊残,有點難以理解炒瘸,不想作過多的解釋

寄生式繼承(構(gòu)造函數(shù)+工廠模式,下面寫錯了)

使用集成式繼承為對象添加函數(shù)寝衫,會由于不能做到函數(shù)復(fù)用而降低效率顷扩;這一點與構(gòu)造函數(shù)模式類似

(常用)寄生組合式繼承

所謂寄生式繼承,通過借用構(gòu)造函數(shù)來繼承屬性慰毅,通過原型鏈的混成形式來繼承方法屎即。其基本的思路是:不必為了制定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),我們所需要的無非就是hi超類型原型的一個副本而已事富。本質(zhì)上,就是使用寄生式繼承來繼承超類型的原型乘陪,然后再將結(jié)果制定給子類型的原型统台。

寄生組合式繼承的基本模式

結(jié)語,在面向?qū)ο笈c原型通過結(jié)合書本和視頻的方式去學習啡邑,本身原型和原型鏈是js的重點難點贱勃。希望在接下來的組件化開發(fā)當中能夠有效地運用起來,不然一切都是紙上談兵

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谤逼,一起剝皮案震驚了整個濱河市贵扰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌流部,老刑警劉巖戚绕,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異枝冀,居然都是意外死亡舞丛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門果漾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來球切,“玉大人,你說我怎么就攤上這事绒障《执眨” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵户辱,是天一觀的道長鸵钝。 經(jīng)常有香客問我,道長焕妙,這世上最難降的妖魔是什么蒋伦? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮焚鹊,結(jié)果婚禮上痕届,老公的妹妹穿的比我還像新娘韧献。我一直安慰自己,他們只是感情好研叫,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布锤窑。 她就那樣靜靜地躺著,像睡著了一般嚷炉。 火紅的嫁衣襯著肌膚如雪渊啰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天申屹,我揣著相機與錄音绘证,去河邊找鬼。 笑死哗讥,一個胖子當著我的面吹牛嚷那,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杆煞,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼魏宽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了决乎?” 一聲冷哼從身側(cè)響起队询,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎构诚,沒想到半個月后蚌斩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡范嘱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年凳寺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彤侍。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡肠缨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盏阶,到底是詐尸還是另有隱情晒奕,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布名斟,位于F島的核電站脑慧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏砰盐。R本人自食惡果不足惜闷袒,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岩梳。 院中可真熱鬧囊骤,春花似錦晃择、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至滑蚯,卻和暖如春浪蹂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背告材。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工坤次, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斥赋。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓浙踢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親灿渴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容