JavaScript 原型對象

JavaScript是一種基于對象的語言法挨,可以說萬物皆對象纳账。
??特別說明:基于對象也好,面向?qū)ο笠埠脤嶋H上都是以對象的概念來編寫程序刹泄,從本質(zhì)上并無區(qū)別外里。
??JavaScript沒有類這個概念,它繼承機制是基于原型特石,產(chǎn)生原型鏈的模式盅蝗,而不是其他語言的類。因此要理解JavaScript的繼承機制姆蘸,需要更深入了解原型對象的概念墩莫。

對象
??JavaScript中,對象是有區(qū)別的逞敷,分為普通對象和函數(shù)對象狂秦,Object、Function是JS自帶的函數(shù)對象推捐,function定義方式本質(zhì)上還是new Function方式故痊。(函數(shù)對象都是通過Function來實例化的)

        <script type="text/javascript">
            function f1(){};
            var f2 = function(){};
            var f3 = new Function('str', 'console.log(str)');
            var o3 = new f1();
            var o1 = {};
            var o2 = new Object();
            
            console.log(typeof Object);//function
            console.log(typeof Function);//function
            console.log(typeof o1);//object
            console.log(typeof o2);//object
            console.log(typeof o3);//object
            console.log(typeof f1);//function
            console.log(typeof f2);//function
            console.log(typeof f3);//function
        </script>

在上面的例子中 o1 o2 o3 為普通對象,f1 f2 f3 為函數(shù)對象玖姑。怎么區(qū)分愕秫,其實很簡單,凡是通過 new Function() 創(chuàng)建的對象都是函數(shù)對象焰络,其他的都是普通對象戴甩。f1,f2闪彼,歸根結(jié)底都是通過 new Function()的方式進行創(chuàng)建的甜孤。Function Object 也都是通過 new Function()創(chuàng)建的协饲。

對象繼承
??Brendan Eich參考C++和Java,做了簡化設(shè)計缴川,將new命令引入到JavaScript中茉稠,new后面跟對象的構(gòu)造函數(shù),用來創(chuàng)建對象把夸,缺點:無法共享方法和屬性而线。

比如,在DOG對象的構(gòu)造函數(shù)中恋日,設(shè)置一個實例對象的共有屬性species膀篮。(函數(shù)也是一個對象)
function DOG(name) {
  this.name = name;
  this.species = '犬科';
};
用上面**函數(shù)對象**生成兩個實例對象
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');

這兩個對象species屬性是獨立的,修改其中一個岂膳,不會影響到另一個誓竿。
dogA.species = '貓科';
alert(dogB.species);//犬科
每個實例對象都有自己的屬性和方法的副本,這不僅無法做到資源共享谈截,也極大的資源浪費筷屡。

Brendan Eich決定為構(gòu)造函數(shù)設(shè)置一個prototype屬性。這個屬性包含一個對象簸喂,所有實例對象需要共享的屬性和方法速蕊,都放在這個對象里面;那些不需要共享的屬性和方法娘赴,就在構(gòu)造函數(shù)里面规哲。實例對象一旦創(chuàng)建,將自動引用prototype對象的屬性和方法(也就是__proto__)诽表。也就是說唉锌,實例對象的屬性和方法,分成兩種竿奏,一種是本地的袄简,另一種是引用的。

species屬性放在prototype對象里泛啸,是兩個實例對象共享的绿语。只要修改了prototype對象,就會同時影響兩個實例對象候址。
DOG.prototype.species = '貓科';
alert(dogA.species);//貓科 (dogA的__proto__指向DOG.prototype)
alert(dogB.species);//貓科

由于所有實例對象共享一個prototype對象吕粹,那么從外界看起來,prototype對象就好像是實例對象的原型岗仑,而實例對象則好像"繼承"了prototype對象一樣匹耕。

原型prototype
??在JavaScript中,每當(dāng)定義一個對象(函數(shù))時候荠雕,對象都會包含一些預(yù)定的屬性稳其。其中函數(shù)對象的一個屬性就是原型對象prototype(原型對象還有constructor屬性(指向構(gòu)造函數(shù)對象))驶赏。普通對象沒有prototype,但是有__proto__屬性既鞠。(比如實例化煤傍、字面量的對象)(指向其原型鏈)

原型對象其實就是普通對象(Function.prototype除外,它是函數(shù)對象,但它很特殊嘱蛋,他沒有prototype屬性(前面說道函數(shù)對象都有prototype屬性))蚯姆。
function f1(){};
console.log(f1.prototype);//f1{}  (f1{}表示普通對象)
console.log(typeof f1.prototype);//object
console.log(typeof Function.prototype);//function,這個特殊
console.log(typeof Object.prototype);//object
console.log(typeof Function.prototype.prototype);//undefined
打印關(guān)于f1函數(shù)對象的相關(guān)信息

原型鏈
??JS在創(chuàng)建對象(不論普通對象還是函數(shù)對象)的時候,都有一個叫做__proto__([[ prototype ]] )的內(nèi)置屬性浑槽,用于指向創(chuàng)建它 的 函數(shù)對象的原型對象prototype。
??(ps:函數(shù)對象來自Function對象返帕,字面量對象來自O(shè)bject對象桐玻,實例對象來自創(chuàng)建它的函數(shù)對象-->等等類似)

var person = function(name) {
    this.name = name;
};
person.prototype.getName = function() {
    return this.name;
}
var gz = new person('gongzi');
gz.getName();//gongzi

以上面的例子為例:

console.log(gz.__proto__ === person.prototype) //true

同樣,person.prototype對象也有__proto__屬性荆萤,它指向創(chuàng)建它的函數(shù)對象(Object)的prototype
console.log(person.prototype.__proto__ === Object.prototype) //true

繼續(xù)镊靴,Object.prototype對象也有__proto__屬性,但它比較特殊链韭,為null
console.log(Object.prototype.__proto__) //null

我們把這個有__proto__串起來的直到Object.prototype.__proto__為null的鏈叫做原型鏈偏竟。
如圖.png
function Fruits(name) {
    this.name = name;
}
Fruits.prototype.colour = 'red';
Object.prototype.taste = '甜';
var fruits = new Fruits('蘋果');
console.log(fruits);//打印實例對象(普通對象)

var Game = {
    name:'王者榮耀'
};
Object.prototype.type = '競技';
console.log(Game);//打印字面量對象(普通對象)

console.log(Fruits.__proto__);//打印 創(chuàng)建它 的 函數(shù)對象 的原型對象,結(jié)果function () {}
console.log(Fruits.constructor);//可以打印出構(gòu)造函數(shù)對象Function//Fruits.__proto__.constructor一樣
Function對象作為一個函數(shù)敞峭,就會有prototype屬性踊谋,該屬性將對應(yīng)”function () {}”對象。
alert(Fruits.__proto__ === Function.prototype);//true

前面有提到旋讹,原型對象屬于普通對象殖蚕。Function.prototype是個例外,它是原型對象沉迹,卻又是函數(shù)對象睦疫,作為一個函數(shù)對象,它又沒有prototype屬性鞭呕。
打印實例對象.png
打印字面量對象.png

constructor屬性
??constructor 屬性返回對創(chuàng)建此對象的函數(shù)的引用
??prototype對象有一個construction屬性蛤育,默認(rèn)指向prototype對象所在的構(gòu)造函數(shù)。
??由于construction屬性定義在prototype對象上面葫松,意味著可以被所有實例對象繼承瓦糕。
??constructor屬性的作用,是分辨原型對象到底屬于哪個構(gòu)造函數(shù)腋么。

總結(jié)
1.原型和原型鏈?zhǔn)莏s實現(xiàn)繼承的一種模式刻坊。
2.原型鏈的形成真正的是靠proto而非prototype。

訪問原型對象的方法
獲取實例對象的原型對象党晋,有三種方法:
1.obj.construction.prototype或者C.prototype用于引用new C()創(chuàng)建的對象的原型對象
2.Object.getPrototypeOf(obj):是獲取obj對象的原型對象的標(biāo)準(zhǔn)方法谭胚。
3.obj.proto:是獲取obj對象的原型對象的非標(biāo)準(zhǔn)方法徐块,每個對象都有的屬性,可以在不支持Object.getPrototypeOf方法時作為權(quán)宜之計灾而,proto是非安全的胡控。
??上面三種方法第一種和第三種都不是很可靠。最新的ES6標(biāo)準(zhǔn)規(guī)定旁趟,proto屬性只有瀏覽器才需要部署昼激,其他環(huán)境可以不部署,obj.construction.prototype在手動改變原型對象時锡搜,可能會失效橙困。

擴展

1.Object.__proto__ === Function.prototype//true
2.Function.__proto__ === Function.prototype//true
3. Function.prototype.__proto__ === Object.prototype//true
1.Object是函數(shù)對象,是通過new Funciton()創(chuàng)建耕餐,所以O(shè)bject.__proto__指向Function.prototype凡傅。

2.Function也是對象函數(shù),也是通過new Function()創(chuàng)建肠缔,所以Function.__proto__指向Function.prototype夏跷。

3.Function.prototype是個函數(shù)對象,理論上其__proto__應(yīng)該指向Functuin.prototype明未,就是它自己槽华,自己指向自己,沒有意義趟妥。函數(shù)對象也是對象猫态,給它設(shè)定根指向Object.prototype,Object.prototype.__proto__ === null披摄,保證原型鏈能夠正常結(jié)束懂鸵。

Object.create()
??創(chuàng)建一個具有指定原型且可選擇性地包含指定屬性的對象。
Object.create(prototype, descriptors)
??這種創(chuàng)建對象的方式與上面所說略有差異行疏,如果要查找原型鏈匆光,按照原型對象的類型分析就可以。
??是使用第一個參數(shù)作為它們的原型酿联。
prototype
??必需终息。要用作原型的對象≌耆茫可以為 null周崭,不繼承任何對象。
descriptors
??可選喳张。包含一個或多個屬性描述符的 JavaScript 對象续镇。
??“數(shù)據(jù)屬性”是可獲取且可設(shè)置值的屬性。 數(shù)據(jù)屬性描述符包含 value 特性销部,以及 writable摸航、enumerable 和 configurable 特性制跟。
使用方法可以參考網(wǎng)絡(luò)上的這兩篇,或自己百度酱虎,沒時間細(xì)說了雨膨。
javascript一種新的對象創(chuàng)建方式-Object.create()
前端開發(fā)者進階之ECMAScript新特性【一】--Object.create

參考文獻:
Javascript繼承機制的設(shè)計思想
JavaScript原型及原型鏈詳解
JS原型、原型鏈深入理解

實在不懂就就就.............這樣記住吧
??JS中所有函數(shù)的原型都是Function.prototype读串,所有對象原型鏈的終點指向Object.prototype

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聊记,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子恢暖,更是在濱河造成了極大的恐慌排监,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杰捂,死亡現(xiàn)場離奇詭異舆床,居然都是意外死亡,警方通過查閱死者的電腦和手機琼娘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門峭弟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來附鸽,“玉大人脱拼,你說我怎么就攤上這事】辣福” “怎么了熄浓?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長省撑。 經(jīng)常有香客問我赌蔑,道長,這世上最難降的妖魔是什么竟秫? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任娃惯,我火速辦了婚禮,結(jié)果婚禮上肥败,老公的妹妹穿的比我還像新娘趾浅。我一直安慰自己,他們只是感情好馒稍,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布皿哨。 她就那樣靜靜地躺著,像睡著了一般纽谒。 火紅的嫁衣襯著肌膚如雪证膨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天鼓黔,我揣著相機與錄音央勒,去河邊找鬼不见。 笑死,一個胖子當(dāng)著我的面吹牛订歪,可吹牛的內(nèi)容都是我干的脖祈。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼刷晋,長吁一口氣:“原來是場噩夢啊……” “哼盖高!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起眼虱,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤喻奥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捏悬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撞蚕,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年过牙,在試婚紗的時候發(fā)現(xiàn)自己被綠了甥厦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡寇钉,死狀恐怖刀疙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扫倡,我是刑警寧澤谦秧,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站撵溃,受9級特大地震影響疚鲤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缘挑,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一集歇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧语淘,春花似錦诲宇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至维贺,卻和暖如春它掂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工虐秋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留榕茧,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓客给,卻偏偏與公主長得像用押,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子靶剑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

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