原型與原型鏈詳解

前言

與大部分面向?qū)ο笳Z言不同隔心,ES6之前中并沒有引入類(class)的概念,JavaScript并非通過類而是直接通過構(gòu)造函數(shù)來創(chuàng)建實(shí)例透揣。在介紹原型和原型鏈之前济炎,我們有必要先復(fù)習(xí)一下構(gòu)造函數(shù)的知識。


一辐真、構(gòu)造函數(shù)

構(gòu)造函數(shù)模式的目的就是為了創(chuàng)建一個自定義類须尚,并且創(chuàng)建這個類的實(shí)例崖堤。構(gòu)造函數(shù)模式中擁有了類和實(shí)例的概念,并且實(shí)例和實(shí)例之間是相互獨(dú)立的耐床,即實(shí)例識別密幔。

構(gòu)造函數(shù)就是一個普通的函數(shù),創(chuàng)建方式和普通函數(shù)沒有區(qū)別撩轰,不同的是構(gòu)造函數(shù)習(xí)慣上首字母大寫胯甩。另外就是調(diào)用方式的不同,普通函數(shù)是直接調(diào)用堪嫂,而構(gòu)造函數(shù)需要使用new關(guān)鍵字來調(diào)用偎箫。

    function Person(name, age, gender) {
        this.name = name
        this.age = age
        this.gender = gender
        this.sayName = function () {
            alert(this.name);
        }
    }
    var per = new Person("孫悟空", 18, "男");
    function Dog(name, age, gender) {
        this.name = name
        this.age = age
        this.gender = gender
    }
    var dog = new Dog("旺財", 4, "雄")
    console.log(per);//當(dāng)我們直接在頁面中打印一個對象時,事件上是輸出的對象的toString()方法的返回值
    console.log(dog);
image

每創(chuàng)建一個Person構(gòu)造函數(shù)皆串,在Person構(gòu)造函數(shù)中淹办,為每一個對象都添加了一個sayName方法,也就是說構(gòu)造函數(shù)每執(zhí)行一次就會創(chuàng)建一個新的sayName方法恶复。這樣就導(dǎo)致了構(gòu)造函數(shù)執(zhí)行一次就會創(chuàng)建一個新的方法怜森,執(zhí)行10000次就會創(chuàng)建10000個新的方法,而10000個方法都是一摸一樣的谤牡,為什么不把這個方法單獨(dú)放到一個地方副硅,并讓所有的實(shí)例都可以訪問到呢?這就需要原型(prototype)

二、原型

在JavaScript中翅萤,每當(dāng)定義一個函數(shù)數(shù)據(jù)類型(普通函數(shù)恐疲、類)時候,都會天生自帶一個prototype屬性断序,這個屬性指向函數(shù)的原型對象流纹,并且這個屬性是一個對象數(shù)據(jù)類型的值。

讓我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系:

image

原型對象就相當(dāng)于一個公共的區(qū)域违诗,所有同一個類的實(shí)例都可以訪問到這個原型對象漱凝,我們可以將對象中共有的內(nèi)容,統(tǒng)一設(shè)置到原型對象中诸迟。

三茸炒、原型鏈

1.__proto__constructor

每一個對象數(shù)據(jù)類型(普通的對象、實(shí)例阵苇、prototype......)也天生自帶一個屬性__proto__壁公,屬性值是當(dāng)前實(shí)例所屬類的原型(prototype)。原型對象中有一個屬性constructor, 它指向函數(shù)對象绅项。

    function Person() {}
    var person = new Person()
    console.log(person.__proto__ === Person.prototype)//true
    console.log(Person.prototype.constructor===Person)//true
    //順便學(xué)習(xí)一個ES5的方法,可以獲得對象的原型
    console.log(Object.getPrototypeOf(person) === Person.prototype) // true
image

2.何為原型鏈

在JavaScript中萬物都是對象紊册,對象和對象之間也有關(guān)系,并不是孤立存在的快耿。對象之間的繼承關(guān)系囊陡,在JavaScript中是通過prototype對象指向父類對象芳绩,直到指向Object對象為止,這樣就形成了一個原型指向的鏈條撞反,專業(yè)術(shù)語稱之為原型鏈妥色。

舉例說明:person → Person → Object ,普通人繼承人類遏片,人類繼承對象類

當(dāng)我們訪問對象的一個屬性或方法時嘹害,它會先在對象自身中尋找,如果有則直接使用吮便,如果沒有則會去原型對象中尋找笔呀,如果找到則直接使用。如果沒有則去原型的原型中尋找,直到找到Object對象的原型线衫,Object對象的原型沒有原型凿可,如果在Object原型中依然沒有找到,則返回undefined授账。

我們可以使用對象的hasOwnProperty()來檢查對象自身中是否含有該屬性;使用in檢查對象中是否含有某個屬性時惨驶,如果對象中沒有但是原型中有白热,也會返回true

    function Person() {}
    Person.prototype.a = 123;
    Person.prototype.sayHello = function () {
      alert("hello");
    };
    var person = new Person()
    console.log(person.a)//123
    console.log(person.hasOwnProperty('a'));//false
    console.log('a'in person)//true

person實(shí)例中沒有a這個屬性,從 person 對象中找不到 a 屬性就會從 person 的原型也就是 person.__proto__ 粗卜,也就是 Person.prototype中查找屋确,很幸運(yùn)地得到a的值為123。那假如 person.__proto__中也沒有該屬性续扔,又該如何查找攻臀?

當(dāng)讀取實(shí)例的屬性時,如果找不到纱昧,就會查找與對象關(guān)聯(lián)的原型中的屬性刨啸,如果還查不到,就去找原型的原型识脆,一直找到最頂層Object為止设联。Object是JS中所有對象數(shù)據(jù)類型的基類(最頂層的類)在Object.prototype上沒有__proto__這個屬性。

console.log(Object.prototype.__proto__ === null) // true

image

如果覺得文章對你有些許幫助灼捂,歡迎在我的GitHub博客點(diǎn)贊和關(guān)注离例,感激不盡!

參考文章

最詳盡的 JS 原型與原型鏈終極詳解悉稠,沒有「可能是」宫蛆。(一)

JavaScript深入之從原型到原型鏈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棵譬,一起剝皮案震驚了整個濱河市线得,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖神郊,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異袖迎,居然都是意外死亡坛缕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門胡诗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邓线,“玉大人,你說我怎么就攤上這事煌恢『С拢” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵瑰抵,是天一觀的道長你雌。 經(jīng)常有香客問我,道長二汛,這世上最難降的妖魔是什么婿崭? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮肴颊,結(jié)果婚禮上氓栈,老公的妹妹穿的比我還像新娘。我一直安慰自己婿着,他們只是感情好授瘦,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竟宋,像睡著了一般提完。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上丘侠,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天徒欣,我揣著相機(jī)與錄音,去河邊找鬼婉陷。 笑死帚称,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的秽澳。 我是一名探鬼主播闯睹,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼担神!你這毒婦竟也來了楼吃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎孩锡,沒想到半個月后酷宵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡躬窜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年浇垦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荣挨。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡男韧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出默垄,到底是詐尸還是另有隱情此虑,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布口锭,位于F島的核電站朦前,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鹃操。R本人自食惡果不足惜韭寸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望组民。 院中可真熱鬧棒仍,春花似錦、人聲如沸臭胜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耸三。三九已至,卻和暖如春浇揩,著一層夾襖步出監(jiān)牢的瞬間仪壮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工胳徽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留积锅,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓养盗,卻偏偏與公主長得像缚陷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子往核,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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