prototype
prototype屬性是每一個函數(shù)都具有的屬性信夫,但它不是一個對象都具有的屬性拢驾。比如:function? Foo(){};? ? ??var foo =new Foo()蹬癌;其中Foo中有prototype屬性衙解,而foo沒有绢掰。但是foo中的隱含的__proto__屬性指向Foo.prototype佳吞。即,foo.__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的孩子,且是雙胞胎侥啤。(雖然不是很好当叭,但是還是很能說明問題的)
如果有一天,發(fā)現(xiàn)孩子的父親其實是Baba盖灸,那么就要修改每一個孩子的father屬性。
也就是說修改了其中一個孩子的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鏈接起來荣瑟。
如果要理清原型和原型鏈的關(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)對象。
那么Object的__proto__指向的是Function.prototype不皆,也即是:Object.__proto__ ===?Function.prototype?//true贯城。
下面再來看Function.prototype的__proto__指向哪里?因為JS中所有的東西都是對象粟焊,那么冤狡,F(xiàn)unction.prototype 也是對象,既然是對象项棠,那么Function.prototype肯定是通過Object創(chuàng)建出來的悲雳,所以,F(xiàn)unction.prototype.__proto__ ===?Object.prototype?//true
綜上所述香追,F(xiàn)unction和Object的原型以及原型鏈的關(guān)系可以歸納為下圖合瓢。
對于單個的對象實例,如果通過Object創(chuàng)建透典,var?obj =?new?Object();那么它的原型和原型鏈的關(guān)系如下圖:
如果通過函數(shù)對象來創(chuàng)建晴楔,
那JavaScript的整體的原型和原型鏈中的關(guān)系就很清晰了,如下圖所示:
轉(zhuǎn)自? https://segmentfault.com/a/1190000014717972