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