與大部分面向?qū)ο笳Z言不同,JavaScript中并沒有引入類(class)的概念抬吟,但JavaScript仍然大量地使用了對(duì)象,為了保證對(duì)象之間的聯(lián)系,JavaScript引入了原型與原型鏈的概念裳朋。
原型
下面是在JavaScript中創(chuàng)建一個(gè)對(duì)象的寫法:
var obj = new FunctionName()
我們可以看出,JavaScript并非通過類而是直接通過構(gòu)造函數(shù)來創(chuàng)建對(duì)象吓著。
JavaScript中所有對(duì)象都有 toString
和valueOf
屬性鲤嫡,給每個(gè)對(duì)象一個(gè)toString
和 valueOf
顯然會(huì)造成極大的浪費(fèi)。為此绑莺,JS的做法是將toString和valueOf放在一個(gè)對(duì)象里暖眼,然后讓每一個(gè)對(duì)象的__proto__
來存儲(chǔ)這個(gè)公共屬性的地址。這個(gè)公共屬性就是原型(proto)
- 每一個(gè)構(gòu)造函數(shù)都擁有一個(gè)
prototype
屬性纺裁,這個(gè)屬性指向一個(gè)對(duì)象诫肠,也就是原型對(duì)象。當(dāng)使用這個(gè)構(gòu)造函數(shù)創(chuàng)建實(shí)例的時(shí)候对扶,prototype屬性指向的原型對(duì)象就成為實(shí)例的原型對(duì)象区赵。- 原型對(duì)象默認(rèn)擁有一個(gè)
constructor
屬性,指向指向它的那個(gè)構(gòu)造函數(shù)(也就是說構(gòu)造函數(shù)和原型對(duì)象是互相指向的關(guān)系)浪南。- 每個(gè)對(duì)象都擁有一個(gè)隱藏的屬性
[[prototype]]
笼才,指向它的原型對(duì)象,這個(gè)屬性可以通過Object.getPrototypeOf(obj)
或obj.__proto__
來訪問络凿。- 實(shí)際上骡送,構(gòu)造函數(shù)的
prototype
屬性與它創(chuàng)建的對(duì)象的[[prototype]]
屬性指向的是同一個(gè)對(duì)象昂羡,即
對(duì)象.__proto__ === 函數(shù).prototype
。
原型鏈
按上文所說摔踱,JavaScript中所有的對(duì)象都有原型對(duì)象虐先。而原型對(duì)象自身也是一個(gè)對(duì)象,它也有自己的原型對(duì)象派敷,這樣層層上溯蛹批,就形成了一個(gè)類似鏈表的結(jié)構(gòu),這就是原型鏈(prototype chain)篮愉。
所有原型鏈的終點(diǎn)都是Object函數(shù)的prototype屬性腐芍,因?yàn)樵贘avaScript中的對(duì)象都默認(rèn)由Object()構(gòu)造。Objec.prototype指向的原型對(duì)象同樣擁有原型试躏,不過它的原型是null猪勇,而null則沒有原型。