2018-09-18

prototype 對象

目錄

1.?原型對象概述

? ? 1.11?構(gòu)造函數(shù)的缺點

? ? 1.2??prototype屬性的作用

????1.3??原型鏈

????1.4??constructor?屬性

2.?instanceof?運算符

面向?qū)ο缶幊毯苤匾囊粋€方面败徊,就是對象的繼承。A 對象通過繼承 B 對象,就能直接擁有 B 對象的所有屬性和方法廉嚼。這對于代碼的復(fù)用是非常有用的叨襟。

大部分面向?qū)ο蟮木幊陶Z言,都是通過“類”(class)來實現(xiàn)對象的繼承钢猛。JavaScript 語言的繼承則是通過“原型對象”(prototype)锈嫩。

1.原型對象概述

1.11構(gòu)造函數(shù)的缺點

JavaScript 通過構(gòu)造函數(shù)生成新對象,因此構(gòu)造函數(shù)可以視為對象的模板甥角。實例對象的屬性和方法网严,可以定義在構(gòu)造函數(shù)內(nèi)部。

上面代碼中嗤无,Cat函數(shù)是一個構(gòu)造函數(shù)震束,函數(shù)內(nèi)部定義了name屬性和color屬性,所有實例對象(上例是cat1)都會生成這兩個屬性当犯,即這兩個屬性會定義在實例對象上面垢村。

通過構(gòu)造函數(shù)為實例對象定義屬性,雖然很方便嚎卫,但是有一個缺點嘉栓。同一個構(gòu)造函數(shù)的多個實例之間,無法共享屬性驰凛,從而造成對系統(tǒng)資源的浪費胸懈。

上面代碼中,cat1和cat2是同一個構(gòu)造函數(shù)的兩個實例恰响,它們都具有meow方法趣钱。由于meow方法是生成在每個實例對象上面,所以兩個實例就生成了兩次胚宦。也就是說首有,每新建一個實例,就會新建一個meow方法枢劝。這既沒有必要井联,又浪費系統(tǒng)資源,因為所有meow方法都是同樣的行為您旁,完全應(yīng)該共享烙常。

這個問題的解決方法,就是 JavaScript 的原型對象(prototype)鹤盒。

1.2prototype 屬性的作用

JavaScript 繼承機制的設(shè)計思想就是蚕脏,原型對象的所有屬性和方法,都能被實例對象共享侦锯。也就是說驼鞭,如果屬性和方法定義在原型上,那么所有實例對象就能共享尺碰,不僅節(jié)省了內(nèi)存挣棕,還體現(xiàn)了實例對象之間的聯(lián)系译隘。

下面,先看怎么為對象指定原型洛心。JavaScript 規(guī)定固耘,每個函數(shù)都有一個prototype屬性,指向一個對象皂甘。

上面代碼中玻驻,函數(shù)f默認(rèn)具有prototype屬性悼凑,指向一個對象偿枕。

對于普通函數(shù)來說,該屬性基本無用户辫。但是渐夸,對于構(gòu)造函數(shù)來說,生成實例的時候渔欢,該屬性會自動成為實例對象的原型墓塌。

上面代碼中,構(gòu)造函數(shù)Animal的prototype屬性奥额,就是實例對象cat1和cat2的原型對象苫幢。原型對象上添加一個color屬性,結(jié)果垫挨,實例對象都共享了該屬性韩肝。

原型對象的屬性不是實例對象自身的屬性。只要修改原型對象九榔,變動就立刻會體現(xiàn)在所有實例對象上哀峻。

上面代碼中,原型對象的color屬性的值變?yōu)閥ellow哲泊,兩個實例對象的color屬性立刻跟著變了剩蟀。這是因為實例對象其實沒有color屬性,都是讀取原型對象的color屬性切威。也就是說育特,當(dāng)實例對象本身沒有某個屬性或方法的時候,它會到原型對象去尋找該屬性或方法先朦。這就是原型對象的特殊之處缰冤。

如果實例對象自身就有某個屬性或方法,它就不會再去原型對象尋找這個屬性或方法烙无。

上面代碼中锋谐,實例對象cat1的color屬性改為black,就使得它不再去原型對象讀取color屬性截酷,后者的值依然為yellow涮拗。

總結(jié)一下,原型對象的作用,就是定義所有實例對象共享的屬性和方法三热。這也是它被稱為原型對象的原因鼓择,而實例對象可以視作從原型對象衍生出來的子對象。

上面代碼中就漾,Animal.prototype對象上面定義了一個walk方法呐能,這個方法將可以在所有Animal實例對象上面調(diào)用。

1.3原型鏈

JavaScript 規(guī)定抑堡,所有對象都有自己的原型對象(prototype)摆出。一方面,任何一個對象首妖,都可以充當(dāng)其他對象的原型偎漫;另一方面,由于原型對象也是對象有缆,所以它也有自己的原型象踊。因此,就會形成一個“原型鏈”(prototype chain):對象到原型棚壁,再到原型的原型……

如果一層層地上溯杯矩,所有對象的原型最終都可以上溯到Object.prototype,即Object構(gòu)造函數(shù)的prototype屬性袖外。也就是說史隆,所有對象都繼承了Object.prototype的屬性。這就是所有對象都有valueOf和toString方法的原因在刺,因為這是從Object.prototype繼承的逆害。

那么,Object.prototype對象有沒有它的原型呢蚣驼?回答是Object.prototype的原型是null魄幕。null沒有任何屬性和方法,也沒有自己的原型颖杏。因此纯陨,原型鏈的盡頭就是null。

上面代碼表示留储,Object.prototype對象的原型是null翼抠,由于null沒有任何屬性,所以原型鏈到此為止获讳。Object.getPrototypeOf方法返回參數(shù)對象的原型阴颖,具體介紹請看后文。

讀取對象的某個屬性時丐膝,JavaScript 引擎先尋找對象本身的屬性量愧,如果找不到钾菊,就到它的原型去找,如果還是找不到偎肃,就到原型的原型去找煞烫。如果直到最頂層的Object.prototype還是找不到,則返回undefined累颂。如果對象自身和它的原型滞详,都定義了一個同名屬性,那么優(yōu)先讀取對象自身的屬性紊馏,這叫做“覆蓋”(overriding)料饥。

注意,一級級向上瘦棋,在整個原型鏈上尋找某個屬性稀火,對性能是有影響的。所尋找的屬性在越上層的原型對象赌朋,對性能的影響越大。如果尋找某個不存在的屬性篇裁,將會遍歷整個原型鏈沛慢。

舉例來說,如果讓構(gòu)造函數(shù)的prototype屬性指向一個數(shù)組达布,就意味著實例對象可以調(diào)用數(shù)組方法团甲。

上面代碼中,mine是構(gòu)造函數(shù)MyArray的實例對象黍聂,由于MyArray.prototype指向一個數(shù)組實例躺苦,使得mine可以調(diào)用數(shù)組方法(這些方法定義在數(shù)組實例的prototype對象上面)。最后那行instanceof表達式产还,用來比較一個對象是否為某個構(gòu)造函數(shù)的實例匹厘,結(jié)果就是證明mine為Array的實例,instanceof運算符的詳細(xì)解釋詳見后文愈诚。

上面代碼還出現(xiàn)了原型對象的contructor屬性,這個屬性的含義下一節(jié)就來解釋牛隅。

1.4constructor 屬性

prototype對象有一個constructor屬性,默認(rèn)指向prototype對象所在的構(gòu)造函數(shù)匕累。

由于constructor屬性定義在prototype對象上面默伍,意味著可以被所有實例對象繼承授霸。

上面代碼中,p是構(gòu)造函數(shù)P的實例對象际插,但是p自身沒有constructor屬性碘耳,該屬性其實是讀取原型鏈上面的P.prototype.constructor屬性。

constructor屬性的作用是框弛,可以得知某個實例對象辛辨,到底是哪一個構(gòu)造函數(shù)產(chǎn)生的。

上面代碼中瑟枫,constructor屬性確定了實例對象f的構(gòu)造函數(shù)是F斗搞,而不是RegExp。

另一方面慷妙,有了constructor屬性僻焚,就可以從一個實例對象新建另一個實例。

上面代碼中膝擂,x是構(gòu)造函數(shù)Constr的實例虑啤,可以從x.constructor間接調(diào)用構(gòu)造函數(shù)。這使得在實例方法中架馋,調(diào)用自身的構(gòu)造函數(shù)成為可能狞山。

上面代碼中,createCopy方法調(diào)用構(gòu)造函數(shù)叉寂,新建另一個實例萍启。

constructor屬性表示原型對象與構(gòu)造函數(shù)之間的關(guān)聯(lián)關(guān)系,如果修改了原型對象屏鳍,一般會同時修改constructor屬性勘纯,防止引用的時候出錯。

上面代碼中钓瞭,構(gòu)造函數(shù)Person的原型對象改掉了驳遵,但是沒有修改constructor屬性,導(dǎo)致這個屬性不再指向Person降淮。由于Person的新原型是一個普通對象超埋,而普通對象的contructor屬性指向Object構(gòu)造函數(shù),導(dǎo)致Person.prototype.constructor變成了Object佳鳖。

所以霍殴,修改原型對象時系吩,一般要同時修改constructor屬性的指向。

上面代碼中月弛,要么將constructor屬性重新指向原來的構(gòu)造函數(shù),要么只在原型對象上添加方法菜皂,這樣可以保證instanceof運算符不會失真恍飘。

如果不能確定constructor屬性是什么函數(shù),還有一個辦法:通過name屬性章母,從實例得到構(gòu)造函數(shù)的名稱乳怎。

2.instanceof 運算符

instanceof運算符返回一個布爾值,表示對象是否為某個構(gòu)造函數(shù)的實例椿胯。

上面代碼中狈醉,對象v是構(gòu)造函數(shù)Vehicle的實例惠险,所以返回true班巩。

instanceof運算符的左邊是實例對象逊桦,右邊是構(gòu)造函數(shù)强经。它會檢查右邊構(gòu)建函數(shù)的原型對象(prototype)匿情,是否在左邊對象的原型鏈上炬称。因此,下面兩種寫法是等價的。

上面代碼中,Object.prototype.isPrototypeOf的詳細(xì)解釋見后文赡译。

由于instanceof檢查整個原型鏈蝌焚,因此同一個實例對象,可能會對多個構(gòu)造函數(shù)都返回true。

上面代碼中涝开,d同時是Date和Object的實例,因此對這兩個構(gòu)造函數(shù)都返回true银舱。

instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype屬性,是否在左邊對象的原型鏈上操软。有一種特殊情況,就是左邊對象的原型鏈上藏澳,只有null對象。這時双炕,instanceof判斷會失真妇斤。

上面代碼中乖酬,Object.create(null)返回一個新對象obj咬像,它的原型是null(Object.create的詳細(xì)介紹見后文)。右邊的構(gòu)造函數(shù)Object的prototype屬性钮惠,不在左邊的原型鏈上蔑赘,因此instanceof就認(rèn)為obj不是Object的實例耙箍。但是旨袒,只要一個對象的原型不是null,instanceof運算符的判斷就不會失真施无。

instanceof運算符的一個用處,是判斷值的類型幢哨。

上面代碼中顽悼,instanceof運算符判斷冰评,變量x是數(shù)組,變量y是對象抛人。

注意,instanceof運算符只能用于對象,不適用原始類型的值续誉。

上面代碼中,字符串不是String對象的實例(因為字符串不是對象)嘹裂,所以返回false。

此外例嘱,對于undefined和null,instanceOf運算符總是返回false。

利用instanceof運算符袜刷,還可以巧妙地解決墩蔓,調(diào)用構(gòu)造函數(shù)時奸披,忘了加new命令的問題洪鸭。

上面代碼使用instanceof運算符卿嘲,在函數(shù)體內(nèi)部判斷this關(guān)鍵字是否為構(gòu)造函數(shù)Fubar的實例。如果不是司蔬,就表明忘了加new命令。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末浮梢,一起剝皮案震驚了整個濱河市芥映,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異刽严,居然都是意外死亡,警方通過查閱死者的電腦和手機倒脓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門饲做,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塞弊,“玉大人泪姨,你說我怎么就攤上這事∽嗪颍” “怎么了唇敞?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵疆柔,是天一觀的道長。 經(jīng)常有香客問我旷档,道長鞋屈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任渠啊,我火速辦了婚禮权旷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著塘装,像睡著了一般卷中。 火紅的嫁衣襯著肌膚如雪十减。 梳的紋絲不亂的頭發(fā)上织阅,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音皂冰,去河邊找鬼。 笑死萍丐,一個胖子當(dāng)著我的面吹牛骨田,可吹牛的內(nèi)容都是我干的箱吕。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼为黎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤揭朝,失蹤者是張志新(化名)和其女友劉穎屯换,沒想到半個月后晕窑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡医咨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了妇穴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞒滴。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡碘举,死狀恐怖蝙场,靈堂內(nèi)的尸體忽然破棺而出售滤,到底是詐尸還是另有隱情弊知,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妹蔽。R本人自食惡果不足惜产园,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一虽另、第九天 我趴在偏房一處隱蔽的房頂上張望贵涵。 院中可真熱鬧宾茂,春花似錦拴还、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弓摘,卻和暖如春韧献,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背势决。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工果复, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人走搁。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像忌栅,于是被迫代替她去往敵國和親曲稼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

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

  • ??面向?qū)ο螅∣bject-Oriented鸭津,OO)的語言有一個標(biāo)志,那就是它們都有類的概念逆趋,而通過類可以創(chuàng)建任意...
    霜天曉閱讀 2,098評論 0 6
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,106評論 0 21
  • 1父泳、不要給自己設(shè)太多的“不可能”吴汪、“不可以”,只有體驗豐富的人生才精彩紛呈杆融。但體驗有底線霜运,比如法律和道德。 2藕各、人...
    長征閱讀 187評論 0 0
  • 感恩父母養(yǎng)育之恩焦除,感恩天地萬物滋養(yǎng)。 感恩每天都有源源不斷像氧氣般的金錢流向我乌逐,感恩宇宙的大愛,感恩認(rèn)識和不認(rèn)識的...
    演權(quán)閱讀 210評論 0 3
  • (一) 偶然間绢慢,看到電影《負(fù)重前行》的視頻剪輯洛波,于是想起了早些看到的《負(fù)重前行》短片。 一個偉大的父親在即將轉(zhuǎn)變成...
    小石子餃子館閱讀 541評論 0 1