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

在瀏覽本文之前首先明白什么是對(duì)象?,在JavaScript中我們會(huì)用typeof( )這個(gè)函數(shù),那么使用typeof( )輸出的值一般會(huì)有number、boolean、string、undefined、function、object等這些類型,那我們本文要研究的就是object和function這兩種類型,返回值是這兩種類型的就是我們本文所要研究的對(duì)象

什么是對(duì)象?

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

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

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

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

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

這不,function就被賦予了skill、skill2、skill3這三個(gè)屬性。

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

function和object的關(guān)系

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

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

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

以上兩個(gè)都是對(duì)象,但是都不是由function創(chuàng)建的,不要忘記了這種寫法只是用字面量的方式來創(chuàng)建對(duì)象的。這種寫法只是為了讓代碼更簡單明了更容易理解。歸根到底以上兩種對(duì)象是由function創(chuàng)建的,請(qǐ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出很多實(shí)例對(duì)象,構(gòu)造函數(shù)和我們平常自定義的函數(shù)沒有語法上的區(qū)別,區(qū)分就是構(gòu)造函數(shù)一般首字母是大寫的。

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

原型(prototype)

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

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

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

function作為對(duì)象,那么他肯定是若干屬性的集合,在JavaScript中,function默認(rèn)有一個(gè)屬性,這個(gè)屬性就是prototype,既然是屬性那么肯定有相對(duì)應(yīng)的屬性值,prototype的屬性值是一個(gè)對(duì)象,既然是對(duì)象,那么肯定是若干屬性的集合,這個(gè)對(duì)象里有一個(gè)默認(rèn)的屬性:constructor,這個(gè)屬性相當(dāng)于一個(gè)'指針',指向這個(gè)函數(shù)本身。
以下圖為例:


prototype既然作為對(duì)象,屬性的集合,不可能就只有constructor這一個(gè)屬性,肯定可以自定義的增加許多屬性,如上圖所示。

上圖還出現(xiàn)了person1這個(gè)實(shí)例函數(shù),他是由構(gòu)造函數(shù)Person實(shí)例化出來的,上文說到每個(gè)function都有prototype這個(gè)屬性,person1也不例外,他的prototype大家會(huì)發(fā)現(xiàn)和Person這個(gè)構(gòu)造函數(shù)的是一樣的,實(shí)例對(duì)象的原型指向的是其構(gòu)造函數(shù)的原型對(duì)象。我們?cè)倏匆欢未a:

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實(shí)例化出來的,而且我們也沒有給person1定義任何屬性,但是person1.name=='Nicholas';這是為什么?那我們就不得不說起-proto-這個(gè)屬性了,每個(gè)對(duì)象都有這個(gè)屬性,這個(gè)屬性一般是隱藏的我們看不到,但是并不妨礙我們?nèi)チ私馑?/p>

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

_ proto_,隱式原型

上文我們提到_ proto_,那到底這個(gè)_ 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

通過看上面的代碼會(huì)發(fā)現(xiàn)結(jié)果為true,你沒有看錯(cuò),這也不是巧合,這是必然的結(jié)果。

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


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

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

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

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

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



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

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

在這里我還要解釋一個(gè)地方,F(xiàn)unction.prototype也是一個(gè)對(duì)象,那其肯定有_ proto_屬性,那么指向誰呢?其指向Object.prototype,為什么呢?Function.prototype是一個(gè)普通的對(duì)象,就可以看成這個(gè)對(duì)象是由Object實(shí)例化出來的,那么Function.prototype._ proto_指向就是Object.prototype了。

下面上一張完整的圖片,大家可以按照下面這種圖片捋一下自己的思路,因?yàn)樯厦嬷v了那么多肯定會(huì)有些亂。



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

繼承

為什么會(huì)說到繼承呢,因?yàn)?strong>繼承是通過原型鏈來體現(xiàn)的,所以一并放在這里講了。我們先看一段代碼:

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

以上代碼中,p1是Person實(shí)例化出來的函數(shù),我并沒有給p1定義name這個(gè)屬性,那p1.name是怎么來的--是從Person.prototype來的,因?yàn)閜1._ proto_指向Person.prototype當(dāng)訪問對(duì)象的某個(gè)屬性時(shí),現(xiàn)在這個(gè)對(duì)象本身去找,如果找不到那就順著_ proto_往上找,直到找到或者Object.prototype為止

由于所有的對(duì)象的原型鏈都會(huì)找到Object.prototype,因此所有的對(duì)象都會(huì)有Object.prototype的方法。這就是所謂的“繼承”。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評(píng)論 0 286
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評(píng)論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評(píng)論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,343評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評(píng)論 2 370

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