JS 中原型和原型鏈深入理解

首先要搞明白幾個概念:

函數(shù)(function)

函數(shù)對象(function object)

本地對象(native object)

內(nèi)置對象(build-in object)

宿主對象(host object)

函數(shù)

function foo(){

}

var foo = function(){

}

前者為函數(shù)聲明,后者為函數(shù)表達(dá)式。typeof foo

的結(jié)果都是function。

函數(shù)對象

函數(shù)就是對象,代表函數(shù)的對象就是函數(shù)對象

官方定義蔓彩, 在Javascript中,每一個函數(shù)實際上都是一個函數(shù)對象.JavaScript代碼中定義函數(shù),或者調(diào)用Function創(chuàng)建函數(shù)時彰居,最終都會以類似這樣的形式調(diào)用Function函數(shù):var newFun = new Function(funArgs, funBody)

其實也就是說竿拆,我們定義的函數(shù)挑辆,語法上鳖藕,都稱為函數(shù)對象魔慷,看我們?nèi)绾稳ナ褂弥欢АH绻覀儐渭兊陌阉?dāng)成一個函數(shù)使用著恩,那么它就是函數(shù),如果我們通過他來實例化出對象來使用蜻展,那么它就可以當(dāng)成一個函數(shù)對象來使用喉誊,在面向?qū)ο蟮姆懂犂锩妫瘮?shù)對象類似于類的概念纵顾。

var foo = new function(){

}

typeof foo // object

或者

function Foo (){

}

var foo = new Foo();

typeof foo // object

上面伍茄,我們所建立的對象

本地對象

ECMA-262 把本地對象(native object)定義為“獨立于宿主環(huán)境的 ECMAScript 實現(xiàn)提供的對象”。簡單來說施逾,本地對象就是 ECMA-262 定義的類(引用類型)敷矫。它們包括:

Object,Function,Array,String,Boolean,Number

Date,RegExp,Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError.

我們不能被他們起的名字是本地對象例获,就把他們理解成對象(雖然是事實上,它就是一個對象曹仗,因為JS中萬物皆為對象)榨汤,通過

typeof(Object)

typeof(Array)

typeof(Date)

typeof(RegExp)

typeof(Math)

返回的結(jié)果都是function

也就是說其實這些本地對象(類)是通過function建立起來的,

function Object(){

}

function Array(){

}

...

可以看出Object原本就是一個函數(shù)怎茫,通過new Object()之后實例化后收壕,創(chuàng)建對象。類似于JAVA中的類轨蛤。

內(nèi)置對象

ECMA-262 把內(nèi)置對象(built-in object)定義為“由 ECMAScript 實現(xiàn)提供的蜜宪、獨立于宿主環(huán)境的所有對象,在 ECMAScript 程序開始執(zhí)行時出現(xiàn)”祥山。這意味著開發(fā)者不必明確實例化內(nèi)置對象圃验,它已被實例化了。ECMA-262 只定義了兩個內(nèi)置對象缝呕,即 Global 和 Math (它們也是本地對象损谦,根據(jù)定義,每個內(nèi)置對象都是本地對象)岳颇。

理清楚了這幾個概念照捡,有助于理解我們下面要講述的原型和原型鏈。

prototype

prototype屬性是每一個函數(shù)都具有的屬性话侧,但是不是一個對象都具有的屬性栗精。比如

function Foo(){

}

var foo = new Foo();

其中Foo中有prototype屬性瞻鹏,而foo沒有悲立。但是foo中的隱含的__proto__屬性指向Foo.prototype。

1foo.__proto__ === Foo.prototype

為什么會存在prototype屬性新博?

Javascript里面所有的數(shù)據(jù)類型都是對象薪夕,為了使JavaScript實現(xiàn)面向?qū)ο蟮乃枷耄捅仨氁軌驅(qū)崿F(xiàn)‘繼承’使所有的對象連接起來赫悄。而如何實現(xiàn)繼承呢原献?JavaScript采用了類似C++,java的方式埂淮,通過new的方式來實現(xiàn)實例姑隅。

舉個例子,child1,child2都是Mother的孩子倔撞,且是雙胞胎讲仰。(雖然不是很好,但是還是很能說明問題的)

function Mother(name){

????this.name = name;

????this.father = 'baba';

}

var child1 = new Mother('huahua');

var child2 = new Mother('huihui');

如果有一天痪蝇,發(fā)現(xiàn)孩子的父親其實是Baba鄙陡,那么就要對孩子每一個孩子的father屬性冕房。

child1.father ='Baba';

console.log(child2.father) // baba

也就是說修改了其中一個孩子的father屬性不會影響到下一個,屬性的值無法共享趁矾。

正是這個原因才提出來prototype屬性毒费,把需要共享的屬性放到構(gòu)造函數(shù)也就是父類的實例中去。

__proto__

__proto__屬性是每一個對象以及函數(shù)都隱含的一個屬性愈魏。對于每一個含有__proto__屬性觅玻,他所指向的是創(chuàng)建他的構(gòu)造函數(shù)的prototype。原型鏈就是通過這個屬性構(gòu)件的培漏。

想像一下溪厘,如果一個函數(shù)對象(也成為構(gòu)造函數(shù))a的prototype是另一個函數(shù)對象b構(gòu)件出的實例,a的實例就可以通過__proto__與b的原型鏈起來牌柄。而b的原型其實就是Object的實例畸悬,所以a的實例對象,就可以通過原型鏈和object的prototype鏈接起來珊佣。

function a(){

}

function b(){

}

var b1 = new b();

a.prototype = b1;

var a1 = new a();

console.log(a1.__proto__===b1);//true

console.log(a1.__proto__.__proto__===b.prototype) //true

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

如果要理清原型和原型鏈的關(guān)系蹋宦,首先要明確一下幾個概念:

1.JS中的所有東西都是對象,函數(shù)也是對象, 而且是一種特殊的對象

2.JS中所有的東西都由Object衍生而來, 即所有東西原型鏈的終點指向Object.prototype

3.JS對象都有一個隱藏的__proto__屬性咒锻,他指向創(chuàng)建它的構(gòu)造函數(shù)的原型冷冗,但是有一個例外,Object.prototype.__proto__指向的是null惑艇。

4.JS中構(gòu)造函數(shù)和實例(對象)之間的微妙關(guān)系

構(gòu)造函數(shù)通過定義prototype來約定其實例的規(guī)格, 再通過 new 來構(gòu)造出實例,他們的作用就是生產(chǎn)對象.

function Foo(){

}

var foo = new Foo();

foo其實是通過Foo.prototype來生成實例的蒿辙。

構(gòu)造函數(shù)本身又是方法(Function)的實例, 因此也可以查到它的__proto__(原型鏈)

function Foo(){

}

等價于

var Foo= new Function();

而Function實際上是

function Function(){

????Native Code

}

也就是等價于

var Function= new Function()滨巴;

所以說Function是通過自己創(chuàng)建出來的思灌。正常情況下對象的__proto__是指向創(chuàng)建它的構(gòu)造函數(shù)的prototype的.所以Function的__proto__指向的Function.prototype

Object 實際上也是通過Function創(chuàng)建出來的

typeof(Object)//function

所以,

function Object(){

????Native Code

}

等價于

var Object = new Function();

那么Object的__proto__指向的是Function.prototype恭取,也即是

1Object.__proto__ === Function.prototype //true

下面再來看Function.prototype的__proto__指向哪里

因為JS中所有的東西都是對象泰偿,那么,F(xiàn)unction.prototype 也是對象蜈垮,既然是對象耗跛,那么Function.prototype肯定是通過Object創(chuàng)建出來的,所以窃款,

1 Function.prototype.__proto__ === Object.prototype //true

綜上所述课兄,F(xiàn)unction和Object的原型以及原型鏈的關(guān)系可以歸納為下圖牍氛。

對于單個的對象實例晨继,如果通過Object創(chuàng)建,

1var obj = new Object();

那么它的原型和原型鏈的關(guān)系如下圖搬俊。

如果通過函數(shù)對象來創(chuàng)建紊扬,

function Foo(){

}

var foo = new Foo();

那么它的原型和原型鏈的關(guān)系如下圖

那JavaScript的整體的原型和原型鏈中的關(guān)系就很清晰了蜒茄,如下圖所示

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市餐屎,隨后出現(xiàn)的幾起案子檀葛,更是在濱河造成了極大的恐慌,老刑警劉巖腹缩,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屿聋,死亡現(xiàn)場離奇詭異,居然都是意外死亡藏鹊,警方通過查閱死者的電腦和手機(jī)润讥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盘寡,“玉大人楚殿,你說我怎么就攤上這事「吞担” “怎么了脆粥?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長影涉。 經(jīng)常有香客問我变隔,道長,這世上最難降的妖魔是什么蟹倾? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任弟胀,我火速辦了婚禮,結(jié)果婚禮上喊式,老公的妹妹穿的比我還像新娘孵户。我一直安慰自己,他們只是感情好岔留,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布夏哭。 她就那樣靜靜地躺著,像睡著了一般献联。 火紅的嫁衣襯著肌膚如雪竖配。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天里逆,我揣著相機(jī)與錄音进胯,去河邊找鬼。 笑死原押,一個胖子當(dāng)著我的面吹牛胁镐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盯漂,長吁一口氣:“原來是場噩夢啊……” “哼颇玷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起就缆,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤帖渠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后竭宰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體空郊,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年切揭,在試婚紗的時候發(fā)現(xiàn)自己被綠了渣淳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡伴箩,死狀恐怖入愧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗤谚,我是刑警寧澤棺蛛,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站巩步,受9級特大地震影響旁赊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜椅野,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一终畅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竟闪,春花似錦离福、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至理朋,卻和暖如春絮识,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗽上。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工次舌, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兽愤。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓彼念,卻偏偏與公主長得像挪圾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子国拇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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