天天看點

JS類的封裝及實作代碼JS類的封裝及實作代碼

js并不是一種面向對向的語言, 沒有提供對類的支援, 是以我們不能像在傳統的語言裡那樣 用class來定義類, 但我們可以利用js的閉包封裝機制來實作js類, 我們來封裝一個簡的shape類.

js并不是一種面向對向的語言, 沒有提供對類的支援, 是以我們不能像在傳統的語言裡那樣 用class來定義類, 但我們可以利用js的閉包封裝機制來實作js類, 我們來封裝一個簡的shape類. 

複制代碼代碼如下:

function shapebase() { 

this.show = function() 

alert("shapebase show"); 

}; 

this.init = function(){ 

alert("shapebase init"); 

這個類裡定義了兩個方法:show和init, 需要注意的是這裡用到了this來聲明, 而不是var, 因為用var是用來定義私有方法的. 

另外, 我們還可以用prototype屬性來定義shape的方法. 

shapebase.prototype.show=function() 

shapebase.prototype.init=function() 

上面這種寫法看起來不太直覺,我們可以将所有的方法寫在一起. 

shapebase.prototype={ 

show:function() 

}, 

init:function() { 

現在, 類是寫好了, 讓我們寫個js來測試下, 看看結果是不是跟我們想象的一樣呢? 

function test(src){ 

var s=new shapebase(); 

s.init(); 

s.show(); 

看到了吧, 其調用方式和c#一模一樣, 而結果也如我們所料. 

到目前為止, 我們學會了如何建立js的類了, 但還隻是執行個體方法,要是實作跟c#中的靜态方法要怎麼做呢? 

其實, 實作js的靜态方法很簡單, 看下面如何實作: 

//靜态方法 

shapebase.staticdraw = function() 

alert("method draw is static"); 

2. 實作js類抽象和繼承 

同樣, js中也不支援類繼承機制,但我們可以通過将父類prototype中的成員方法複制到子類的prototype中來實作. 

和類的繼承一樣,javascript也沒有任何機制用于支援抽象類.但利用javascript語言本身的性質.可以實作自己的抽象類. 

首先來看看js中的虛方法, 在傳統語言中虛方法是要先定義的, 而包含虛方法的類就是抽象類,不能被執行個體化,而在javascript中,虛方法就可以看作該類中沒有定義的方法,但已經通過this指針使用了. 

和傳統面向對象不同的是,這裡虛方法不需經過聲明,而直接使用了, 并且類也可以被執行個體化. 

先定義object的extend方法, 一個為靜态方法,一個為執行個體方法, 這兩個方法用于實作繼承的prototype複制 

object.extend = function(destination, source) { 

for (property in source) { 

destination[property] = source[property]; 

return destination; 

object.prototype.extend = function(object) { 

return object.extend.apply(this, [this, object]); 

接下來我們實作一個繼承類rect, 這裡先用一種簡單的方法來實作。 

function rect() { 

rect.prototype = shapebase.prototype; //隻這一句就行了 

//擴充新的方法 

rect.prototype.add=function() { 

alert("rect add"); 

這種方法不能用于重寫,如果改變了show方法, shapebase的show也會指向同一函數可能是由于prototype指派隻是簡單的改變指向位址. 

如果上面也定義了: 

rect.prototype.show=function() { 

alert("rect show"); 

那麼執行結果如下: 

function test(){ 

s.show(); //結果:rect show 

var r=new rect(); 

r.show(); //結果:rect show 

r.add(); 

我們再使用object.extend實作繼承, 并實作一個oninit虛方法, 修改shapebase如下: 

initialize:function () { 

this.oninit(); 

實作rect類繼承. 

rect.prototype=(new shapebase).extend({ 

//添加新的方法 

add:function() { 

//使用這種方法可以重寫show方法 

show:function() { 

//實作虛方法 

oninit:function() { 

alert("rect oninit"); 

}) 

現在我們的類寫好了, 測試下看看: 

shapebase.staticdraw(); 

s.show(); //alert("shapebase show") 

r.show(); //alert("rect show") 

r.initialize(); //alert("rect oninit") 

另外,在網上看到一篇用專門的對象來建立類,代碼如下: 

// 

//對象屬性複制方法,很多庫都有實作,如prototypejs裡面的extend和ext裡面的ext.apply 

function extend(des, src) { 

if (!des) 

des = {}; 

if (src) { 

for (var i in src) { 

des[i] = src[i]; 

return des; 

var cc = {}; //全局變量 

//create 用于建立類 

cc.create = function(superclass, constructor){ 

var clazz = (function() { 

this.initialize.apply(this, arguments); 

}); 

//如果無參數,直接傳回類. 

if(arguments.length == 0) 

return clazz; 

//如果無父類,此時constructor應該為一個純對象,直接複制屬性傳回. 

if(!superclass){ 

extend(clazz.prototype, constructor); 

var absobj = clazz.prototype, 

sprpropty = superclass.prototype; 

if(sprpropty){ 

//用于通路父類方法 

clazz.superclass = sprpropty; 

extend(absobj, sprpropty); 

//調用屬性構造函數建立屬性,這個是實作關鍵. 

extend(absobj, constructor(sprpropty)); 

// 子類執行個體直接通過obj.superclass通路父類屬性, 

// 如果不想造成過多引用,也可把這句注釋掉,因為多數時候是沒必要的. 

absobj.superclass = sprpropty; 

clazz.constructor = constructor; 

//建立一個動物類 

var animal = cc.create(null, { 

//屬性 

footprint : '- - - - - - =', 

//類初始化方法,必須的,當用 new 生成一個類時該方法自動被調用,參見上定義. 

initialize : function(options){ 

extend(this, options); 

alert('animal initialize method is called.'); 

eat : function(){ 

alert('animal eat method is called.'); 

move : function(){ 

alert('i am moving like this '+ this.footprint +' .'); 

//建立一個duke類 

var duke = cc.create(animal, function(superclass){ 

//在這可以定義一些類全局靜态資料,該類每個執行個體都共享這些資料. 

//計算執行個體個類,包括派生類執行個體. 

var static_instance_counter = 0; 

function classutilityfunchere(){ } 

//傳回類具體屬性. 

return { 

//重寫初始化方法 

//@override 

initialize : function(options) { 

alert('initializing duke class..'); 

//調用父類初始化,這種方法比一般其它庫的要簡潔點吧,可以不管父類是什麼. 

superclass.initialize.call(this, options); 

//做一些子類喜歡做的事. 

alert('duke initialize method is called.'); 

//讀取或修改類靜态屬性 

static_instance_counter++; 

//重寫move方法,增加duke自己的移動方式. 

this.footprint = this.footprint + 'zzzzzzzz'; 

superclass.move.call(this); 

//重寫eat方法,注意,裡面不調用父類方法,即父類eat被覆寫了. 

alert('duke is eating..'); 

//新增一個say方法,顯示目前已經初始化的duke類執行個體數量. 

say : function(){ 

alert('the number of duke instances is '+static_instance_counter); 

var dukechild = cc.create(duke, function(superclass){ 

this.footprint = this.footprint + '++++++++++++='; 

alert(this.msg || ''); 

(function test() { 

var animal = new animal(); 

animal.eat(); 

animal.move(); 

var dukea = new duke(); 

dukea.eat(); 

dukea.move(); 

dukea.say(); 

var dukeb = new duke(); 

dukeb.eat(); 

dukeb.move(); 

dukeb.say(); 

var dukec = new dukechild({msg : 'i am a child of duke.'}); 

dukec.move(); 

dukec.say(); 

})(); 

特别說明:尊重作者的勞動成果,轉載請注明出處哦~~~http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp67

繼續閱讀