關(guān)于原型和原型鏈的詳細(xì)理解

在瀏覽本文之前首先明白什么是對象?妖胀,在JavaScript中我們會用typeof( )這個函數(shù)芥颈,那么使用typeof( )輸出的值一般會有number、boolean赚抡、string爬坑、undefined、function涂臣、object等這些類型盾计,那我們本文要研究的就是object和function這兩種類型,返回值是這兩種類型的就是我們本文所要研究的對象赁遗。

什么是對象署辉?

那么對象該如何去定義呢?我個人認(rèn)為對象就是一些屬性的集合岩四。舉個栗子??

 var Laowang={
     'name':'老王',
     'feature':'熱心腸',
     'skill':function( ){
          alert('特長是修水管');
 }
}

那么在上面的例子中'Laowang'就是一個對象哭尝,你肯定會有疑問關(guān)于我對對象的定義,在'Laowang'這個對象中出現(xiàn)了function方法剖煌,但是這個方法在'Laowang'這個對象中是以鍵值對的形式出現(xiàn)的材鹦,所以這個function就是'skill'這個屬性的屬性值。所以驗證了對象就是一些屬性的集合這句話耕姊。

上面的例子很好理解桶唐,但是數(shù)組和函數(shù)好像不能這樣去定義屬性,但他們也是對象啊茉兰,不要迷惑莽红,他們有自己定義屬性的方法。以函數(shù)為例:

var laowang=function( ){
      alert('修水管');
}
laowang.skill='熱心腸';
laowang.skill2='愛串門';
laowang.skill3={
    'a':'親切問候鄰居家孩子'
}

這不邦邦,function就被賦予了skill安吁、skill2、skill3這三個屬性燃辖。

上面說到function和objec這兩個返回值是對象鬼店,既然都是對象,為什么返回的不是一個值黔龟。由于function和object的關(guān)系比較特殊所以返回的值不同妇智,我在下文會詳細(xì)講到function和object的'特殊關(guān)系'

function和object的關(guān)系

上文說道function和object都是對象氏身,但是function的返回值是function而不是object巍棱,那么他倆之間肯定有某種'神秘的關(guān)系'。

function和object的關(guān)系其實就像'先有蛋還是先有雞'這種讓你抓狂的問題蛋欣。function是object的一種航徙,但是object又是由function創(chuàng)建的,什么陷虎,你要打我臉到踏?

var arr=['a','b','c'];
var obj={
    'name':'老王',
    'age':'99'
}

以上兩個都是對象杠袱,但是都不是由function創(chuàng)建的,不要忘記了這種寫法只是用字面量的方式來創(chuàng)建對象的窝稿。這種寫法只是為了讓代碼更簡單明了更容易理解楣富。歸根到底以上兩種對象是由function創(chuàng)建的,請看以下代碼:

var arr=new Arry('a','b','c');
var obj=new Object();
obj.name='老王';
obj.age='99';

在以上代碼中Arry( )和Object( )都是函數(shù)伴榔,通常我們把他們當(dāng)做構(gòu)造函數(shù)纹蝴,由構(gòu)造函數(shù)我們可以new出很多實例對象,構(gòu)造函數(shù)和我們平常自定義的函數(shù)沒有語法上的區(qū)別踪少,區(qū)分就是構(gòu)造函數(shù)一般首字母是大寫的骗灶。

是不是感覺很亂?為什么function和object的關(guān)系是這樣的秉馏,不要慌張耙旦,耐心看完本文你就會豁然開朗。

原型(prototype)

上面扯了半天對象萝究,到這里終于講到本文的主要內(nèi)容了--原型(prototype)免都。

那么prototype到底是什么呢?不要著急帆竹,讓我們一步步來绕娘。

上面我們說到function也是一種對象,現(xiàn)在對這個應(yīng)該沒有任何疑問了栽连,如果有疑問請滑動你的鼠標(biāo)從頭開始看O樟臁!

function作為對象秒紧,那么他肯定是若干屬性的集合绢陌,在JavaScript中,function默認(rèn)有一個屬性熔恢,這個屬性就是prototype脐湾,既然是屬性那么肯定有相對應(yīng)的屬性值,prototype的屬性值是一個對象叙淌,既然是對象秤掌,那么肯定是若干屬性的集合,這個對象里有一個默認(rèn)的屬性:constructor鹰霍,這個屬性相當(dāng)于一個'指針'闻鉴,指向這個函數(shù)本身。
以下圖為例:


prototype既然作為對象茂洒,屬性的集合孟岛,不可能就只有constructor這一個屬性,肯定可以自定義的增加許多屬性,如上圖所示蚀苛。

上圖還出現(xiàn)了person1這個實例函數(shù)在验,他是由構(gòu)造函數(shù)Person實例化出來的玷氏,上文說到每個function都有prototype這個屬性堵未,person1也不例外,他的prototype大家會發(fā)現(xiàn)和Person這個構(gòu)造函數(shù)的是一樣的盏触,實例對象的原型指向的是其構(gòu)造函數(shù)的原型對象渗蟹。我們再看一段代碼:

var Person=function(){};
  Person.prototype.name='Nicholas';
  Person.prototype.age='29';
  Person.prototype.job='Software Engineer';
var person1=new Person();
console.log(person1.name); // 'Nicholas'
console.log(person1.age); // '29'

在上面代碼中person1是由構(gòu)造函數(shù)Person實例化出來的,而且我們也沒有給person1定義任何屬性赞辩,但是person1.name=='Nicholas';這是為什么雌芽?那我們就不得不說起-proto-這個屬性了,每個對象都有這個屬性辨嗽,這個屬性一般是隱藏的我們看不到世落,但是并不妨礙我們?nèi)チ私馑?/p>

這個屬性指向了創(chuàng)建這個對象的構(gòu)造函數(shù)的prototype。即:person1._ proto_ ===Person.prototype糟需,下面我們來看看這個'_ proto_'是什么鬼屉佳。

_ proto_,隱式原型

上文我們提到_ proto_,那到底這個_ proto_是什么呢洲押?我看下面的代碼:

var Person=function(){};
  Person.prototype.name='Nicholas';
  Person.prototype.age='29';
  Person.prototype.job='Software Engineer';
var person1=new Person();
  console.log(person1._proto_===Person.prototype);//true

通過看上面的代碼會發(fā)現(xiàn)結(jié)果為true武花,你沒有看錯,這也不是巧合杈帐,這是必然的結(jié)果体箕。

實質(zhì)上person1是被Person實例化出來的,那么person1._ proto_===Person.prototype挑童,下面用圖給你展示一下:


上圖的o1和o2是由Object實例化出來的累铅,他們的_ proto_指向的是Object.prototype,這就說明:每個對象都有一個_ proto_屬性站叼,指向創(chuàng)建該對象的構(gòu)造函數(shù)的prototype争群。

那么你肯定會問'每個對象都有一個_ proto_屬性,指向創(chuàng)建該對象的構(gòu)造函數(shù)的prototype'大年,那Object也是一個對象换薄,肯定也有_ proto_屬性,那他指向誰翔试?

關(guān)于Object._ proto_的指向問題很特殊轻要,在這個Object._ proto_是個特例,它指向null垦缅,這個地方大家一定要牢記冲泥。

也許你還會有另一個疑問,函數(shù)也是對象,實例化出來的函數(shù)的_ proto_屬性指向其構(gòu)造函數(shù)凡恍,那么其構(gòu)造函數(shù)的_ proto_指向誰志秃?

Function這個前面沒有提到,現(xiàn)在拿出來曬曬嚼酝,構(gòu)造函數(shù)是由誰創(chuàng)建的浮还,就是由Function這個函數(shù)創(chuàng)建的,所以你上面的疑問就很好解答了闽巩。再用一張圖讓你更清晰的看清他們的關(guān)系:



這張圖清晰的表明了自定義構(gòu)造函數(shù)钧舌、Object、Function之間的關(guān)系涎跨!

眼神好的人會在上圖發(fā)現(xiàn)一個問題:自定義函數(shù)Foo._ proto_指向Function.prototype洼冻,Object._ proto_指向Function.prototype,怎么Function._ proto_也指向Function.prototype隅很,這不就是形成了一個'死循環(huán)'么撞牢,來,讓我們仔細(xì)捋一捋叔营,F(xiàn)unction也是一個函數(shù)屋彪,既然是函數(shù)那么他肯定是由Function創(chuàng)建的,那么上面的'死循環(huán)'就解釋通了审编。

在這里我還要解釋一個地方撼班,F(xiàn)unction.prototype也是一個對象,那其肯定有_ proto_屬性垒酬,那么指向誰呢砰嘁?其指向Object.prototype,為什么呢?Function.prototype是一個普通的對象勘究,就可以看成這個對象是由Object實例化出來的矮湘,那么Function.prototype._ proto_指向就是Object.prototype了。

下面上一張完整的圖片口糕,大家可以按照下面這種圖片捋一下自己的思路缅阳,因為上面講了那么多肯定會有些亂。



這張圖完整的呈現(xiàn)出了實例對象景描、自定義函數(shù)十办、Object、Function之間種種錯綜復(fù)雜的關(guān)系超棺,不要怕麻煩向族,一條一條的去找對應(yīng)的關(guān)系。

繼承

為什么會說到繼承呢棠绘,因為繼承是通過原型鏈來體現(xiàn)的件相,所以一并放在這里講了再扭。我們先看一段代碼:

function Person(){  }
  var p1=new Person();
  Person.prototype.name='老王';
  Person.prototype.age='99';
  console.log(p1.name);//'老王'

以上代碼中,p1是Person實例化出來的函數(shù)夜矗,我并沒有給p1定義name這個屬性泛范,那p1.name是怎么來的--是從Person.prototype來的,因為p1._ proto_指向Person.prototype紊撕,當(dāng)訪問對象的某個屬性時罢荡,現(xiàn)在這個對象本身去找,如果找不到那就順著_ proto_往上找逛揩,直到找到或者Object.prototype為止柠傍。

由于所有的對象的原型鏈都會找到Object.prototype麸俘,因此所有的對象都會有Object.prototype的方法辩稽。這就是所謂的“繼承”。

講到這里从媚,關(guān)于原型和原型鏈就結(jié)束了逞泄,希望各位能深刻的理解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拜效,一起剝皮案震驚了整個濱河市喷众,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌紧憾,老刑警劉巖到千,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赴穗,居然都是意外死亡憔四,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門般眉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來了赵,“玉大人,你說我怎么就攤上這事甸赃∈裂矗” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵埠对,是天一觀的道長络断。 經(jīng)常有香客問我,道長项玛,這世上最難降的妖魔是什么貌笨? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮稍计,結(jié)果婚禮上躁绸,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好净刮,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布剥哑。 她就那樣靜靜地躺著,像睡著了一般淹父。 火紅的嫁衣襯著肌膚如雪株婴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天暑认,我揣著相機(jī)與錄音困介,去河邊找鬼。 笑死蘸际,一個胖子當(dāng)著我的面吹牛座哩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播粮彤,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼根穷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了导坟?” 一聲冷哼從身側(cè)響起屿良,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惫周,沒想到半個月后尘惧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡递递,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年喷橙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漾狼。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡重慢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逊躁,到底是詐尸還是另有隱情似踱,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布稽煤,位于F島的核電站核芽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏酵熙。R本人自食惡果不足惜轧简,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匾二。 院中可真熱鬧哮独,春花似錦拳芙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悴务,卻和暖如春睹限,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讯檐。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工羡疗, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人别洪。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓叨恨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蕉拢。 傳聞我的和親對象是個殘疾皇子特碳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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