原型與原型鏈

ECMAScript規(guī)定全區(qū)對象叫做global隘弊,但是瀏覽器把window作為全局對象(瀏覽器先存在)window就是一個哈希表哈踱,有很多屬性,window的屬性就是全局變量梨熙。
window下面的屬性分為兩類开镣,第一類是ECMAScript規(guī)定必須有的函數(shù),第二類是私有的(瀏覽器專有咽扇,標準不一)邪财。

簡單類型與對象的區(qū)別:

//全局函數(shù)
//1.Number
var n = new Number(1)//創(chuàng)建一個Number對象
1與new Number(1)的區(qū)別是什么?看內(nèi)存圖
//2.String
var s = new String('hello')//創(chuàng)建一個Number對象
'hello'與new String('hello')的區(qū)別是什么质欲?看內(nèi)存圖
//3.boolean
var b = new Boolean(true)//創(chuàng)建一個Number對象
true與new Boolean(true)的區(qū)別是什么树埠?看內(nèi)存圖
//4.Object
var o1 = {}
var o2 = new Object()
o1和o2沒區(qū)別

簡單數(shù)據(jù)類型和通過new 構造函數(shù)創(chuàng)建的數(shù)據(jù)對象(除了對象)區(qū)別在于內(nèi)存地址不同,前者存放在stack中,而后者存放在heap里嘶伟。

image.png

將數(shù)值通過Number包裝成對象弥奸,內(nèi)存里面就有許多操作該數(shù)值的方法。但簡單數(shù)據(jù)也可以調(diào)用這些辦法奋早,那為什么還需要將數(shù)值包裝成對象呢?
答:歷史原因赠橙,在發(fā)明JS時模仿JAVA聲明數(shù)據(jù)(new關鍵字耽装,滿足老板需求),第二種可以直接聲明var a =1期揪。 由于第二種方法無法使用toString等方法(只有對象才能使用方法掉奄,簡單數(shù)據(jù)類型不可以),創(chuàng)始人使用了一個妙計(臨時轉換)當寫n.toString時凤薛,隱式的聲明一個temp為 new Number(n)姓建,然后再調(diào)用n.toString的值為temp,再銷毀temp數(shù)據(jù)缤苫。臨時的轉換速兔,用完就銷毀了。所以給簡單數(shù)據(jù)類型加屬性讀取時將會報錯活玲,這種方法受到了開發(fā)人員的歡迎涣狗。
image.png

公有的屬性藏在哪?

所有的對象都有toStringvalueOf屬性舒憾,那么我們是否有必要給每個對象一個toStringvalueOf呢镀钓?
明顯不需要(內(nèi)存不允許),JS的做法是把toStringvalueOf放在一個對象里镀迂,暫且叫做公有屬性組成的對象(原型)丁溅。

對象分為普通對象和函數(shù)對象,ObjectFunction是js自帶的函數(shù)對象探遵,每個對象都有原型(null和undefined除外)可以理解為對象的默認屬性和方法窟赏。

字符串對象

通過new string()方法轉換成的字符串對象是一個哈希妓柜,每一個字符對應相應的索引值,使用方括號或者charAt(索引值)來獲取相對應的字符饰序,charCodeAt(索引值)獲取對應索引的值的編碼领虹。繼承了String對象的方法。
獲取一個數(shù)字對應的進制值使用toString()方法求豫,如(100).toString(16)//64 可以將字符的編碼轉化為其他進制的編碼

布爾值對象

image.png

簡單數(shù)據(jù)類型false和布爾對象false在被轉換時是不相等的塌衰。


image.png

為什么不相等?雖然兩個對象都沒有名字蝠嘉,但存放在heap中的地址值不同最疆,自然不會相等,請牢記5個假值,對象經(jīng)過布爾轉換為真值蚤告。


image.png

結論:所有新聲明的對象都是不相等的努酸。除非將一個對象的地址值賦值給另一個變量。

Number String Boolean Object通過以上幾種方式創(chuàng)建的對象都具有toString杜恰、valueof方法获诈,這兩個方法哪里來的呢?如果在每個新生成對象里面都定義這兩個方法太占內(nèi)存心褐。實現(xiàn)繼承的方法:原型鏈

要清楚原型鏈舔涎,首先先弄清楚對象。

普通對象,有____proto____屬性(指向其原型鏈)逗爹,沒有prototype屬性亡嫌。
原型對象,構造函數(shù).prototype原型對象還有constructor屬性指向構造函數(shù)對象
函數(shù)對象,通過new Function()創(chuàng)建的都是函數(shù)對象掘而。用有prototype寻仗、____proto____屬性(指向原型對象)

原型鏈概念

ECMAScript中描述了原型鏈的機制犹菇,將原型鏈作為實現(xiàn)繼承的主要方式叛本。其基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法艺玲。

在js中,每個對象都有一個指向它的原型對象的內(nèi)部鏈接女蜈,這個原型對象又有自己的原型持舆,直到某個對象的原型為null為止(也就是不再有原型指向),組成這條鏈的最后一環(huán)伪窖。這種一級一級的鏈接結構就稱為原型鏈逸寓。

JS對象有一個指向一個原型對象的鏈,當試圖訪問一個對象的屬性時覆山,它不僅僅在該對象上搜尋竹伸,還會搜尋該對象的原型,以及該對象原型的原型,依此層層向上搜索勋篓,直到找到一個名字匹配的屬性或到達原型鏈的末尾吧享。

所有引用類型默認都繼承了Object,而這個繼承也是通過原型鏈實現(xiàn)的譬嚣,所有函數(shù)的默認原型都是Object的實例钢颂,因此默認原型都會包含一個內(nèi)部指針,指向Object.prototype拜银。這也正是所有自定義類型都會繼承toString()殊鞭,valueOf()等默認方法的根本原因,所有函數(shù)的原型最頂端都有一個最終的對象原型尼桶,存儲著對象本身自帶方法和屬性操灿,當調(diào)用實例上的toString()等方法時,實際上是調(diào)用的是保存在Object.prototype中的那個方法泵督。


簡單回顧一下構造函數(shù)趾盐、原型和實例之間的關系:每創(chuàng)建一個函數(shù)都有一個prototype屬性指向通過該構造函數(shù)創(chuàng)建實例對象的原型對象,原型對象是包含特定類型的所有實例共享的屬性和方法小腊,都包含了一個指向構造函數(shù)的指針救鲤,而實例都包含一個指向原型對象的____proto____內(nèi)部指針。

iSQ05n.jpg

iSQs2V.jpg

下面是一個簡單的例子:

//原型鏈實例
//構造函數(shù)Animal
function Animal(){
    this.type = "animal"
}
//Animal構造函數(shù)定義原型方法
Animal.prototype.getType = function(){
    return this.type
}
//Dog構造函數(shù)
function Dog(){
    this.name = 'dog'
}
//Dog構造函數(shù)定義原型方法
Dog.prototype.getName = function(){
    return this.name
}
//Dog原型等于構造函數(shù)Animal實例(實現(xiàn)繼承)
Dog.prototype = new Animal()
//構建新實例
var xiaohuang = new Dog()

實例秩冈、構造函數(shù)蜒简、原型之間的關系。

xiaohuang.__proto__ === Dog.prototype
Dog.prototype.__proto__ === Animal.prototype
Animal.prototype === Object.prototype
Object.prototype.proto === null
//總結:xiaohuang這個Dog的實例繼承了Animal,Animal繼承了Object
console.log(xiaohuang.type)//'animal'
console.log(xiaohuang.name)//'dog'

iSQHKO.jpg

iSQqqe.jpg

總結:
iSQXad.md.jpg

兩個構造函數(shù)漩仙,將其中一個構造函數(shù)的實例賦值給另一個構造函數(shù)的原型,這樣另一個原型就有了指向前面那一個構造函數(shù)的原型的指針(創(chuàng)建的實例也會有同樣的原型鏈)犹赖,查找屬性和方法會根據(jù)原型鏈來進行搜索队他,先搜索實例,再搜索原型峻村,最后是原型的原型.....麸折,注意此時實例的constructor指向了最開始的構造函數(shù)垢啼,而不是創(chuàng)建實例的函數(shù)(為了代碼的嚴謹吞瞪,可以設置為創(chuàng)建此實例的函數(shù))惯疙。實現(xiàn)的本質是重寫原型對象对碌,代之以一個新類型的實例朽们。原型鏈繼承不僅會繼承原型上面的屬性和方法,還會繼承實例上的方法和屬性。


Object原型對象,怎么讓每個對象都指向這個共有屬性歹袁?
答:每個對象都有一個__proto__屬性指向了共有屬性乏矾。

對象和數(shù)值對象:

var o1 = new Number(1);
var o2 =new Object(1);
o1===o2   //false
o1.toString()===o2.toString() //true

兩個數(shù)值對象不相等,因為stack存放的heap地址值不同凄硼,但使用的toString函數(shù)是公共屬性(Number的原型的屬性)痒给,因此相等(new Object(1)自動轉換成了數(shù)值對象)。

iSQMEd.png

Object()函數(shù)不加new操作符會根據(jù)傳入的參數(shù)生成相應的數(shù)據(jù)類型的對象,對于Object函數(shù)來說爬橡,加不加new都是一樣的效果。

String()函數(shù)不加new操作符是將你給定的參數(shù)變成string常量(基本類型,非對象),而加上new會生成String對象(復雜類型,字符串對象)搀暑,除了Object函數(shù)以外脉让,其他的標準庫函數(shù)都是一樣的效果埠啃。

數(shù)值的toString()方法和對象的toString()方法并不相等博秫,因為前者可以加進制參數(shù)而且會被先搜尋到朴爬。

image.png

調(diào)用方法時逸爵,會經(jīng)過一層一層的查找周蹭。Number String Boolean Object都有自己的共有屬性,____proto____都是先指向了自己的共有屬性,共有屬性的__proto____再指向了對象。
image.png

如果對象的共有屬性沒有被引用的話囚玫,必將會被回收读规,object.prototype指向(引用)這個共有屬性(原型)
image.png

當你聲明一個對象時抓督,JS引擎除了在棧內(nèi)存里面存放一個hash之外,還將____proto____指向了你該有的共有屬性(原型)束亏。

不寫代碼就有prototype

在沒有代碼的時候铃在,Number.prototypeObject.prototype碍遍、String.prototype定铜、Boolean.prototype都引用了各自的共有屬性(保證不被垃圾回收機制回收),是JS定義的,不可更改的怕敬。而你的對象____proto____則指向了對應數(shù)據(jù)類型的prototype揣炕。

image.png

初始化數(shù)據(jù)類型里面還有一個Function.prototype,存儲了函數(shù)的原型(共有方法)东跪,Function也是一個對象畸陡,Function.__proto__指向了Function.prototype鹰溜,使用函數(shù)初始化對象時(new Function()),該函數(shù)對象的____proto____就指向了Function.prototype(因為Function是Object的構造函數(shù))丁恭,而Function.prototype里面的____proto____就指向了Object.prototype曹动。

image.png

繼承方式:子類構造函數(shù).prototype= new 父類構造函數(shù) ,簡單說就是將父類的實例賦值給子類的原型涩惑,這樣子類的____proto____屬性
目前組合繼承用的最多仁期,構造函數(shù)模式定義實例屬性(不可共享),原型模式則定義方法和共享的屬性竭恬。

現(xiàn)在你明白什么是原型和原型鏈了嗎跛蛋?:)

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市痊硕,隨后出現(xiàn)的幾起案子赊级,更是在濱河造成了極大的恐慌,老刑警劉巖岔绸,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件理逊,死亡現(xiàn)場離奇詭異,居然都是意外死亡盒揉,警方通過查閱死者的電腦和手機晋被,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刚盈,“玉大人羡洛,你說我怎么就攤上這事∨菏” “怎么了欲侮?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肋联。 經(jīng)常有香客問我威蕉,道長,這世上最難降的妖魔是什么橄仍? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任韧涨,我火速辦了婚禮,結果婚禮上侮繁,老公的妹妹穿的比我還像新娘虑粥。我一直安慰自己,他們只是感情好鼎天,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著暑竟,像睡著了一般斋射。 火紅的嫁衣襯著肌膚如雪育勺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天罗岖,我揣著相機與錄音涧至,去河邊找鬼。 笑死桑包,一個胖子當著我的面吹牛南蓬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哑了,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼赘方,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了弱左?” 一聲冷哼從身側響起窄陡,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拆火,沒想到半個月后跳夭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡们镜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年币叹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模狭。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡颈抚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胞皱,到底是詐尸還是另有隱情邪意,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布反砌,位于F島的核電站雾鬼,受9級特大地震影響,放射性物質發(fā)生泄漏宴树。R本人自食惡果不足惜策菜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酒贬。 院中可真熱鬧又憨,春花似錦、人聲如沸锭吨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽零如。三九已至躏将,卻和暖如春锄弱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祸憋。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工会宪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蚯窥。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓掸鹅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拦赠。 傳聞我的和親對象是個殘疾皇子巍沙,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

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