關(guān)于JS原型你所需要知道的全部

JS之Prototypal Inheritance

本文解釋了:

  1. prototype concept

  2. inheritance concept

  3. 原型鏈的概念及用法

  4. 修改原型的危害

  5. 非基本數(shù)據(jù)類型自帶一些屬性和方法

  6. 基本數(shù)據(jù)自帶對(duì)象包裝Object wrapper

  7. prototype concept

By default, every function has a property called prototype. This property by default is empty and you can add properties and methods to it. When you create object from this function, e.g. if I create X1 from X, it would inherit these properties and methods that define X's prototype.


原型的概念
  1. inheritance concept

  • One object gets access to the properties and methods of another object.
  • All JavaScript objects inherit properties and methods from a prototype.
  1. 原型鏈 prototype chain

原型鏈簡(jiǎn)圖

每個(gè)對(duì)象都有一個(gè) prototype豺鼻,每個(gè) prototype 也是一個(gè)對(duì)象。每個(gè)對(duì)象是通過(guò)自己的 prototype 來(lái)繼承屬性和方法的款慨;
JavaScript自帶原型鏈搜索功能儒飒,如上圖的obj.prop2實(shí)際上是obj.prototype.prop2, obj.prop3也是obj.prototype.prototype.prop3, 但是我們不用手動(dòng)地這樣層層地去找這個(gè)屬性究竟是在哪一個(gè)prototype的對(duì)象里,JS直接幫我們找了檩奠,所以直接調(diào)用obj.prop2等就可以桩了。
同樣,我們也可以**手動(dòng)修改對(duì)象的原型埠戳,使它指向別的對(duì)象(by reference):

var person = {
  firstName: 'default',
  lastName: 'default',
  getFullName: function() {
    return this.firstName + ' ' + this.lastName;
  }
}

var john = {
  firstName : 'John',
  lastName : 'Doe'
}

//手動(dòng)設(shè)置把john的原型指向person object
john.__proto__ = person;
console.log(john.getFullName()); //John Doe
console.log(john.firstName); //John

注意井誉,最后的console.log(john.firstName);的結(jié)果是John而非person里的default,是因?yàn)?code>john對(duì)象本身就自帶firstName這個(gè)屬性整胃,在原型鏈的頂端颗圣,JS引擎在原型從上到下層層遞找,所以當(dāng)JS引擎在原型鏈頂端找到方法和屬性后屁使,就停止再往下找在岂,直接調(diào)用再頂端的(也就是john對(duì)象)的firstName屬性。此外蛮寂,也要注意蔽午,當(dāng)person對(duì)象的getFullName()方法加入John對(duì)象的原型后,里面的this就指向了john對(duì)象酬蹋。
同理及老,如果在上方的代碼塊下再加上以下代碼,會(huì)得到:

var jane = {
  firstName : 'Jane'
}
jane.__proto__ = person;
console.log(jane.getFullName()); //Jane default
  1. 修改原型的危害

修改對(duì)象的原型在實(shí)際生活中是一個(gè)十分危險(xiǎn)的舉動(dòng)除嘹,一旦被修改写半,之后所聲明擁有同一原型的新對(duì)象將受到牽連岸蜗。例如:
   const num = 42;
=> undefined
   num.toString();
=> '42'
   Number.prototype.toString = function() {return '100'};
=> [Function]
   num.toString();
=> '100'
   num
=> 42
   const num2 = 50;
=> undefined
   num2.toString();
=> '100'
   

從上例可以看出尉咕,當(dāng)把整個(gè)Number對(duì)象原型中的toString()方法修改后,所有的number對(duì)象里的方法也都被改寫(xiě)璃岳。

  1. 非基本數(shù)據(jù)類型自帶一些屬性和方法

  • Array.prototype.push()
  • String.prototype.toUpperCase()
    比如說(shuō)我們?cè)跒g覽器自帶的console里聲明一個(gè)變量const arr = ['value', 'value1']可以得到以下的結(jié)果
    在console里輸入arr和它的原型

*#### Each object stores a reference to its prototype.每個(gè)對(duì)象都存儲(chǔ)了對(duì)其原型的引用年缎。(即每個(gè)對(duì)象都知道原型自帶的屬性和方法)

  • Properties/Methods defined most tightly to the instance have priority.

比如說(shuō)在當(dāng)arr.proto和arr.proto.proto兩個(gè)object都包含同樣的功能toString,但當(dāng)我們?cè)谡{(diào)用arr.toString的時(shí)候,實(shí)際調(diào)用的是arr.proto.toString,就如arr雖然既是array又是object铃慷,但是相較之下稱呼其為array更具體单芜,arr.proto.toString也比arr.proto.proto.toString更specific,離arr這個(gè)instance更近犁柜。

  1. Most primitive types have object wrappers

  • String()
  • Number()
  • Boolean()
  • Object()
  • (Symbol())
    這里要注意的是洲鸠,雖然我們之前說(shuō)只有非基本數(shù)據(jù)類型才自帶一些屬性和方法,但是基本數(shù)據(jù)類型卻自帶對(duì)象包裝(object wrapper),而這些包裝也是自帶原型的,所以可以調(diào)用原型的方法扒腕。即JS will automatically box(wrap) primitive values so you have access to the methods.
42.toString();   // Errors(還未包裝)
const x = 42;(包裝后)
x.toString();    //'42'
x.__proto__;  //[Number: 0]
x instanceof Number // false

這里也要注意>畹怼!瘾腰!最后一個(gè)例子中的instanceofoperator**運(yùn)算符用于測(cè)試構(gòu)造函數(shù)的prototype屬性是否出現(xiàn)在對(duì)象的原型鏈中的任何位置皆的。而此處的x只是為了引用方法的對(duì)Number對(duì)象的包裝(It's just boxed around that number object for your reference)。
同理"foo" instanceof String //false蹋盆;String("foo") instanceof String //true费薄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市栖雾,隨后出現(xiàn)的幾起案子楞抡,更是在濱河造成了極大的恐慌,老刑警劉巖岩灭,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拌倍,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡噪径,警方通過(guò)查閱死者的電腦和手機(jī)柱恤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)找爱,“玉大人梗顺,你說(shuō)我怎么就攤上這事〕瞪悖” “怎么了寺谤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)吮播。 經(jīng)常有香客問(wèn)我变屁,道長(zhǎng),這世上最難降的妖魔是什么意狠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任粟关,我火速辦了婚禮,結(jié)果婚禮上环戈,老公的妹妹穿的比我還像新娘闷板。我一直安慰自己,他們只是感情好院塞,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布遮晚。 她就那樣靜靜地躺著,像睡著了一般拦止。 火紅的嫁衣襯著肌膚如雪县遣。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音萧求,去河邊找鬼括蝠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饭聚,可吹牛的內(nèi)容都是我干的忌警。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼秒梳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼法绵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起酪碘,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤朋譬,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后兴垦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體徙赢,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年探越,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狡赐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钦幔,死狀恐怖枕屉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鲤氢,我是刑警寧澤搀擂,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站卷玉,受9級(jí)特大地震影響哨颂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜相种,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一威恼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蚂子,春花似錦沃测、人聲如沸缭黔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)馏谨。三九已至别渔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哎媚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工喇伯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拨与。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓稻据,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親买喧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捻悯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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