有兩個(gè)基本的創(chuàng)建對(duì)象的方法挥吵。
一是采用字面量的方式裤唠,如下
二是采用構(gòu)造函數(shù)砂客,先定義一個(gè)函數(shù)泥张,再通過new來創(chuàng)建一個(gè)該函數(shù)的事例。
可以看出上面的例子有明顯的問題鞠值,名字和和年齡在構(gòu)造函數(shù)中被固定媚创,導(dǎo)致不能復(fù)用,將其改造一下彤恶,可以再加上一個(gè)方法hello()钞钙。如下,一個(gè)最簡(jiǎn)單由構(gòu)造函數(shù)創(chuàng)建的對(duì)象就完成了声离,它有name和age兩個(gè)屬性芒炼,有一個(gè)hello()方法。
這種生成對(duì)象的方式有什么缺點(diǎn)呢术徊?那就是每次創(chuàng)建新的實(shí)例都會(huì)都會(huì)為實(shí)例單獨(dú)創(chuàng)建一個(gè)方法本刽,例如創(chuàng)建一個(gè)叫huahua的實(shí)例,var huahua = new Person("huahua",15)赠涮,此時(shí)dongdong.hello()和huahua.hello()兩個(gè)方法是相互獨(dú)立的子寓。這導(dǎo)致創(chuàng)建的方法不能被復(fù)用。一般采用原型屬性的方式來解決這個(gè)問題笋除。
這里涉及到了一個(gè)非常重要的概念别瞭,原型。我們創(chuàng)建的每一個(gè)函數(shù)都有一個(gè)原型屬性(prototype)株憾,這個(gè)屬性指向?qū)嵗蚕淼膶傩院头椒簿褪钦f如果將函數(shù)的方法直接添加到原型屬性中晒衩,那么所有實(shí)例共享這個(gè)方法,而不用每次在生成實(shí)例時(shí)創(chuàng)建該方法墙歪。如下:
此時(shí)如果生成兩個(gè)實(shí)例听系,dongdong和huahua,他們的hello()方法是相同的虹菲,都指向在原型的hello()靠胜。
那么為什么我們不將所有的屬性和方法都定義在原型中呢?因?yàn)槿绻麑傩员欢x在原型中毕源,那么所有的實(shí)例都會(huì)有一樣的屬性值浪漠,而對(duì)于包含引用類型值的屬性來說(簡(jiǎn)單來說就是包含多個(gè)值的屬性)這個(gè)問題就會(huì)比較突出,每個(gè)實(shí)例對(duì)數(shù)組做出的改變都是針對(duì)原型的霎褐,因此會(huì)反映到其他所有實(shí)例上址愿。
理一下這時(shí)的原型指向關(guān)系,Person的原型同時(shí)也是dongdong和huahua的原型冻璃,Person原型的constructor是Person响谓。
繼承
js中繼承主要通過原型鏈來實(shí)現(xiàn),基本思想是讓一個(gè)對(duì)象繼承另一個(gè)對(duì)象的屬性和方法省艳。在使用構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí)娘纷,實(shí)例指向原型對(duì)象,我們可以運(yùn)用這一特性跋炕,讓一個(gè)原型對(duì)象等于某個(gè)函數(shù)的實(shí)例赖晶,這時(shí)這個(gè)原型對(duì)象指向這個(gè)函數(shù)的原型,形成了原型鏈辐烂。
上圖中遏插,Student的原型等于Person的一個(gè)實(shí)例,即Student的原型的原型是Person的原型棉圈,形成了原型鏈,當(dāng)查找值時(shí)會(huì)先查找實(shí)例眷蜓,找不到就去找實(shí)例的原型分瘾,再找原型的原型,最終找不到返回null吁系。
原型鏈有什么問題呢德召?從上面對(duì)象創(chuàng)建過程中可以看到,我們之所以不將屬性定義到原型中汽纤,是因?yàn)樵椭袑傩院头椒ㄔ谏蓪?shí)例時(shí)上岗,所有的實(shí)例都會(huì)有同樣的屬性值。然而在原型鏈中蕴坪,由于“Student的原型等于Person的一個(gè)實(shí)例”肴掷,Student的原型繼承了Person實(shí)例的屬性和方法敬锐,導(dǎo)致Student的實(shí)例會(huì)有同樣的來自Person實(shí)例的屬性和方法,尤其是包含多個(gè)值的屬性呆瞻。為了解決這一問題通常采用組合繼承的方法台夺。
這樣Student通過call繼承了Person中的屬性,通過原型鏈繼承了方法痴脾,完美解決了上述問題颤介。
一點(diǎn)心得,如需轉(zhuǎn)載請(qǐng)注明出處赞赖。