【JS原型&原型鏈】一張圖說清楚

JavaScript原型&原型鏈

原型鏈圖

原型鏈.png

如果你看到這張圖一臉懵助被,不要怕钧大,往下看竟稳,下面會一步一步教你認(rèn)識原型&原型鏈

前置知識

js的初學(xué)者一般很難理解原型和原型鏈的概念健蕊,但原型和原型鏈又是js中最重要的點(diǎn)之一。從jQuery到現(xiàn)在最火的框架之一Vue罩缴,原型的應(yīng)用無處不在蚊逢,那我們該怎么學(xué)好JavaScript的原型和原型鏈呢?

  • 想要弄清楚原型和原型鏈箫章,這幾個(gè)屬性必須要搞清楚烙荷,__proto__prototype 檬寂、 constructor终抽。
  • 其次你要知道js中對象和函數(shù)的關(guān)系,函數(shù)其實(shí)是對象的一種桶至。
  • 最后你要知道函數(shù)昼伴、構(gòu)造函數(shù)的區(qū)別,任何函數(shù)都可以作為構(gòu)造函數(shù)镣屹,但是并不能將任意函數(shù)叫做構(gòu)造函數(shù)圃郊,只有當(dāng)一個(gè)函數(shù)通過new關(guān)鍵字調(diào)用的時(shí)候才可以成為構(gòu)造函數(shù)。如:
var Parent = function(){

}
//定義一個(gè)函數(shù)女蜈,那它只是一個(gè)普通的函數(shù)持舆,下面我們讓這個(gè)函數(shù)變得不普通
var p1 = new Parent();
//這時(shí)這個(gè)Parent就不是普通的函數(shù)了,它現(xiàn)在是一個(gè)構(gòu)造函數(shù)鞭光。因?yàn)橥ㄟ^new關(guān)鍵字調(diào)用了它
//創(chuàng)建了一個(gè)Parent構(gòu)造函數(shù)的實(shí)例 p1

如果到這你都能理解吏廉,
我們再引出一個(gè)概念泞遗,開始說過了要想清楚原型就要先搞清楚惰许,__proto__prototype 史辙、 constructor汹买。

  • 我們記住兩點(diǎn)
    1.__proto__constructor屬性是對象所獨(dú)有的聊倔;
    2.prototype 屬性是函數(shù)獨(dú)有的晦毙;
    3.上面說過js中函數(shù)也是對象的一種,那么函數(shù)同樣也有屬性__proto__耙蔑、 constructor

下面開始進(jìn)入正題↓↓↓

1.prototype屬性

prototype屬性.png

它是函數(shù)獨(dú)有的屬性见妒,它從一個(gè)函數(shù)指向另一個(gè)對象,代表這個(gè)對象是這個(gè)函數(shù)的原型對象甸陌,這個(gè)對象也是當(dāng)前函數(shù)所創(chuàng)建的實(shí)例的原型對象须揣。
prototype設(shè)計(jì)之初就是為了實(shí)現(xiàn)繼承盐股,讓由特定函數(shù)創(chuàng)建的所有實(shí)例共享屬性和方法,也可以說是讓某一個(gè)構(gòu)造函數(shù)實(shí)例化的所有對象可以找到公共的方法和屬性耻卡。有了prototype我們不需要為每一個(gè)實(shí)例創(chuàng)建重復(fù)的屬性方法疯汁,而是將屬性方法創(chuàng)建在構(gòu)造函數(shù)的原型對象上(prototype)。那些不需要共享的才創(chuàng)建在構(gòu)造函數(shù)中卵酪。
繼續(xù)引用上面的代碼幌蚊,當(dāng)我們想為通過Parent實(shí)例化的所有實(shí)例添加一個(gè)共享的屬性時(shí),

Parent.prototype.name = "我是原型屬性溃卡,所有實(shí)例都可以讀取到我";

這就是原型屬性溢豆,當(dāng)然你也可以添加原型方法。那問題來了瘸羡,p1怎么知道他的原型對象上有這個(gè)方法呢沫换,往下看↓↓↓

2.proto屬性

proto屬性.png

__proto__屬性是對象(包括函數(shù))獨(dú)有的。__proto__屬性是從一個(gè)對象指向另一個(gè)對象最铁,即從一個(gè)對象指向該對象的原型對象(也可以理解為父對象)讯赏。顯然它的含義就是告訴我們一個(gè)對象的原型對象是誰。
prototype篇章我們說到冷尉,在上面添加的屬性和方法叫做原型屬性和原型方法漱挎,該構(gòu)造函數(shù)的實(shí)例都可以訪問調(diào)用。那這個(gè)構(gòu)造函數(shù)的原型對象上的屬性和方法雀哨,怎么能和構(gòu)造函數(shù)的實(shí)例聯(lián)系在一起呢磕谅,就是通過__proto__屬性。每個(gè)對象都有__proto__屬性雾棺,該屬性指向的就是該對象的原型對象膊夹。

p1.__proto__ === Parent.prototype; // true

__proto__通常稱為隱式原型,prototype通過成為顯示原型捌浩,那我們可以說一個(gè)對象的隱式原型指向了該對象的構(gòu)造函數(shù)的顯示原型放刨。那么我們在顯示原型上定義的屬性方法,通過隱式原型傳遞給了構(gòu)造函數(shù)的實(shí)例尸饺。這樣一來實(shí)例就能很容易的訪問到構(gòu)造函數(shù)原型上的方法和屬性了进统。
我們之前也說過__proto__屬性是對象(包括函數(shù))獨(dú)有的,那么Parent.prototype也是對象浪听,那它有隱式原型么螟碎?又指向誰?

Parent.prototype.__proto__ === Object.prototype; //true

可以看到迹栓,構(gòu)造函數(shù)的原型對象上的隱式原型對象指向了Object的原型對象掉分。那么Parent的原型對象就繼承了Object的原型對象。由此我們可以驗(yàn)證一個(gè)結(jié)論,萬物繼承自O(shè)bject.prototype酥郭。這也就是為什么我們可以實(shí)例化一個(gè)對象尔崔,并且可以調(diào)用該對象上沒有的屬性和方法了。如:

//我們并沒有在Parent中定義任何方法屬性褥民,但是我們可以調(diào)用
p1.toString();//hasOwnProperty 等等的一些方法

我們可以調(diào)用很多我們沒有定義的方法季春,這些方法是哪來的呢?現(xiàn)在引出原型鏈的概念消返,當(dāng)我們調(diào)用p1.toString()的時(shí)候载弄,先在p1對象本身尋找,沒有找到則通過p1.__proto__找到了原型對象Parent.prototype撵颊,也沒有找到宇攻,又通過Parent.prototype.__proto__找到了上一層原型對象Object.prototype。在這一層找到了toString方法倡勇。返回該方法供p1使用逞刷。
當(dāng)然如果找到Object.prototype上也沒找到,就在Object.prototype.__proto__中尋找妻熊,但是Object.prototype.__proto__ === null 所以就返回undefined夸浅。這就是為什么當(dāng)訪問對象中一個(gè)不存在的屬性時(shí),返回undefined了扔役。

3.constructor屬性

constructor屬性.png

constructor是對象才有的屬性帆喇,它是從一個(gè)對象指向一個(gè)函數(shù)的。指向的函數(shù)就是該對象的構(gòu)造函數(shù)亿胸。每個(gè)對象都有構(gòu)造函數(shù)坯钦,好比我們上面的代碼p1就是一個(gè)對象,那p1的構(gòu)造函數(shù)是誰呢侈玄?我們打印一下婉刀。

console.log(p1.constructor); // ? Parent(){}

通過輸出結(jié)果看到,很顯然是Parent函數(shù)序仙。我們有說過函數(shù)也是對象突颊,那Parent函數(shù)是不是也有構(gòu)造函數(shù)呢?顯然是有的诱桂。再次打印下洋丐。

console.log(Parent.constructor); // ? Function() { [native code] }

通過輸出看到Parent函數(shù)的構(gòu)造函數(shù)是Function(),這點(diǎn)也不奇怪挥等,因?yàn)槲覀兠看味x函數(shù)其實(shí)都是調(diào)用了new Function(),下面兩種效果是一樣的堤尾。

var fn1 = new Function('msg','alert(msg)');
function fn1(msg){
    alert(msg);
}

那么我們再回來看下肝劲,再次打印Function.constructor

console.log(Function.constructor); // ? Function() { [native code] }

可以看到Function函數(shù)的構(gòu)造函數(shù)就是本身了,那我們也就可以說Function是所有函數(shù)的根構(gòu)造函數(shù)。
到這里我們已經(jīng)對constructor屬性有了一個(gè)初步的認(rèn)識辞槐,它的作用是從一個(gè)對象指向一個(gè)函數(shù)掷漱,這個(gè)函數(shù)就是該對象的構(gòu)造函數(shù)。通過栗子我們可以看到榄檬,p1constructor屬性指向了Parent卜范,那么Parent就是p1的構(gòu)造函數(shù)。同樣Parentconstructor屬性指向了Function鹿榜,那么Function就是Parent的構(gòu)造函數(shù)海雪,然后又驗(yàn)證了Function就是根構(gòu)造函數(shù)。

總結(jié)

  • 看到這我相信大家已經(jīng)對原型和原型鏈有了一定的理解了舱殿,還沒有特別理解的同學(xué)也不要擔(dān)心奥裸,原型原型鏈以及閉包都是js中最難的幾部分,需要一定的技術(shù)積累和時(shí)間沉淀沪袭。每天打開文章看一遍湾宙,自己畫一遍這個(gè)原型鏈的圖,因?yàn)槠渲杏行┰硎钦f不出來的冈绊,得靠自己去體會理解侠鳄。不積跬步無以至千里不積小流無以成江海。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末死宣,一起剝皮案震驚了整個(gè)濱河市畦攘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌十电,老刑警劉巖知押,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鹃骂,居然都是意外死亡台盯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門畏线,熙熙樓的掌柜王于貴愁眉苦臉地迎上來静盅,“玉大人,你說我怎么就攤上這事寝殴≥锏” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵蚣常,是天一觀的道長市咽。 經(jīng)常有香客問我,道長抵蚊,這世上最難降的妖魔是什么施绎? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任溯革,我火速辦了婚禮,結(jié)果婚禮上谷醉,老公的妹妹穿的比我還像新娘致稀。我一直安慰自己,他們只是感情好俱尼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布抖单。 她就那樣靜靜地躺著,像睡著了一般遇八。 火紅的嫁衣襯著肌膚如雪矛绘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天押蚤,我揣著相機(jī)與錄音蔑歌,去河邊找鬼。 笑死揽碘,一個(gè)胖子當(dāng)著我的面吹牛次屠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雳刺,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼劫灶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了掖桦?” 一聲冷哼從身側(cè)響起本昏,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤劣挫,失蹤者是張志新(化名)和其女友劉穎武氓,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體独旷,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雀久,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年宿稀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赖捌。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祝沸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出越庇,到底是詐尸還是另有隱情罩锐,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布卤唉,位于F島的核電站涩惑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏搬味。R本人自食惡果不足惜境氢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一蟀拷、第九天 我趴在偏房一處隱蔽的房頂上張望碰纬。 院中可真熱鬧萍聊,春花似錦、人聲如沸悦析。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽强戴。三九已至亭螟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間骑歹,已是汗流浹背预烙。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留道媚,地道東北人扁掸。 一個(gè)月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像最域,于是被迫代替她去往敵國和親谴分。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

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