关于原型的一点总结
?
原型(prototype)無(wú)疑是JavaScript中一個(gè)十分重要的概念,圍繞著原型所涉及的原型鏈繼承、內(nèi)建對(duì)象擴(kuò)展,JS表現(xiàn)出獨(dú)特的面向?qū)ο筇匦浴?/p>
?
? ? ?1.什么是原型 ? ? ?每個(gè)JS的函數(shù)對(duì)象中都有一個(gè)默認(rèn)的prototype屬性,它指向的就是這個(gè)函數(shù)對(duì)象的原型對(duì)象,其初始值是一個(gè)沒(méi)有自身屬性“空對(duì)象”。(實(shí)際上含有指向構(gòu)造函數(shù)的constructor屬性以及指向Object.prototype的__proto__屬性),來(lái)看: function Test(){this.a = 'a';this.b = function(){return 'b';} } Test.prototype;?
? ? ?2.對(duì)原型進(jìn)行擴(kuò)展 ? ? ?對(duì)于這個(gè)“空”原型對(duì)象我們可以進(jìn)行擴(kuò)展,添加屬性或方法(方法實(shí)質(zhì)也是一種指向匿名函數(shù)的特殊屬性)從而加強(qiáng)函數(shù)的功能。這與在構(gòu)造函數(shù)中添加屬性進(jìn)行擴(kuò)展的區(qū)別是,后者定義的屬性在只存在于原型對(duì)象里(原型屬性或方法僅此一份,類(lèi)似Java中的類(lèi)屬性或方法)而實(shí)例對(duì)象本身并沒(méi)有這個(gè)屬性(實(shí)例對(duì)象可以通過(guò)原型鏈__proto__訪問(wèn)到原型的這個(gè)屬性),在實(shí)際應(yīng)用中的具體表現(xiàn)是原型對(duì)象屬性具有“實(shí)時(shí)性”,一旦改變?cè)蛯?duì)象的屬性所有實(shí)例對(duì)象的這個(gè)屬性都會(huì)變化(因?yàn)樵揪褪且粋€(gè)東東,常說(shuō)的對(duì)象函數(shù)復(fù)用就是這里啦)。 ? ? ?3.利用實(shí)例屬性重寫(xiě)原型屬性 ? ? ?如果原型屬性和實(shí)例屬性重名,實(shí)例屬性具有更高優(yōu)先級(jí),JS引擎會(huì)優(yōu)先查找實(shí)例屬性返回。另外可以用hasOwnProperty()方法檢測(cè)某屬性究竟是不是自身屬性。在查找某對(duì)象屬性時(shí)會(huì)按照原型鏈進(jìn)行逐級(jí)查找(一直到Object.prototype),其原理如下: ? ? ?每個(gè)對(duì)象(實(shí)例對(duì)象、構(gòu)造函數(shù)、原型對(duì)象)其實(shí)都有__proto__屬性。在這里,實(shí)例對(duì)象的__proto__指向自己的原型對(duì)象,構(gòu)造函數(shù)的指向Function.prototype(這里將構(gòu)造函數(shù)看作Function的一個(gè)實(shí)例),原型對(duì)象的__proto__指向Object.prototype(將原型對(duì)象看做Object的一個(gè)實(shí)例),原型鏈就是通過(guò)__proto__層層追溯,直到Object.__proto__=null,直接上圖(版權(quán)歸圖片作者所有):? ? ?在用for-in循環(huán)查找對(duì)象的所有屬性時(shí),結(jié)果所列出的是原型鏈中的所有實(shí)例屬性和原型屬性。那么問(wèn)題來(lái)了,如何判斷一個(gè)方法究竟是實(shí)例屬性還是原型屬性呢,這里可以用到obj.hasOwnProperty(propName).另外還可“迂回”通過(guò):propertyIsEnmuberable(propName)方法來(lái)判斷。
function Triangle(a,b,c){this.a = a;this.b = b;this.c = c;this.sides = [a,b,c];this.Perimeter = function(){return this.a+this.b+this.c;} } Triangle.prototype.dimension = '2d'; Triangle.prototype.getPoints = function(){return '3'; }?
? ? ?4.isPropertyOf( )方法和__proto__ ? ? ?prototype.isPropertyOf(obj)可用于判斷一個(gè)實(shí)例對(duì)象是否是另一個(gè)對(duì)象的原型,這個(gè)方法也可用于判斷繼承關(guān)系(原型鏈繼承的實(shí)現(xiàn)就是將子類(lèi)構(gòu)造函數(shù)的原型對(duì)象指向父類(lèi)的一個(gè)實(shí)例對(duì)象)。 5.利用原型擴(kuò)展內(nèi)建對(duì)象 ? ? ?我們可以利用擴(kuò)展的工作原理,對(duì)一些內(nèi)建的構(gòu)造函數(shù)(如Array,String)進(jìn)行一些擴(kuò)展,使之具備一些自定義的屬性或方法。 ? ? ?例如,字符串中并沒(méi)有反轉(zhuǎn)方法,我們可以對(duì)其原型進(jìn)行擴(kuò)展來(lái)添加這種方法,這里借助了數(shù)組的反轉(zhuǎn)方法String.reverse() String.prototype.reverse = function(){Array.prototype.reverse.apply(this.split('').join('')); }當(dāng)然這種修改內(nèi)置對(duì)象的做法有可能會(huì)導(dǎo)致第三方庫(kù)在使用內(nèi)置對(duì)象時(shí)產(chǎn)生一些錯(cuò)誤,或是導(dǎo)致新出現(xiàn)的內(nèi)置方法被我們的修改覆蓋,這時(shí)最好在添加前先做一下判斷該屬性是否已經(jīng)存在。
?
6.重寫(xiě)原型對(duì)象時(shí)的坑 為毛要重寫(xiě)原型?因?yàn)楹芏嗲闆r下要實(shí)現(xiàn)另一種繼承方式。不是已經(jīng)有原型鏈繼承了么?沒(méi)錯(cuò),但是原型鏈繼承方式的子類(lèi)實(shí)例會(huì)共享父類(lèi)實(shí)例的引用值屬性,兩個(gè)新new的子類(lèi)實(shí)例如果一個(gè)改變了自己的引用屬性另一個(gè)實(shí)例會(huì)同樣變化(僅限引用值屬性,基本值屬性還是獨(dú)立的),所以這個(gè)缺陷導(dǎo)致此種繼承能應(yīng)用受限!!! ? ? ?重寫(xiě)原型對(duì)象時(shí)注意重置constructor屬性,因?yàn)樾陆ǖ膶?duì)象一般是作為Object的實(shí)例而單獨(dú)存在其prototype.constructor默認(rèn)指向Object( )(當(dāng)然也可能是其他已知實(shí)例,但同樣需要調(diào)整防止重寫(xiě)后原型依然指向原來(lái)的構(gòu)造函數(shù)).ES5中可以用Object.getPropertyOf( )來(lái)檢測(cè)其自身原型對(duì)象究竟是神馬。 好了,關(guān)于原型的一點(diǎn)總結(jié)暫告段落,文中如有錯(cuò)誤和不規(guī)范的地方還請(qǐng)各位朋友多多指正,謝過(guò)先!?
轉(zhuǎn)載于:https://www.cnblogs.com/mengda1027/p/4497027.html
總結(jié)
- 上一篇: TCPUDP测试工具的使用
- 下一篇: 关于 QueryDSL 配置和使用(详细