Javascript中建立對象可歸納為三種方式:工廠函數、建構函式和原型方式。
工廠函數方式利用javascript基礎類Object,對Object的一個執行個體增加相應的屬性和方法以達到新類型所期望的結果。如下代碼展示了類型NewClassType1含有一個屬性attribute1。
//工廠函數方式,返回特定類型的對象執行個體 functionNewClassType1(){ varo = new Object(); o.attribute1= 3; returno; };
擷取NewClassType1類型的執行個體,類似於設計模式中的Factory 方法,直接調用即可。如下代碼展示擷取NewClassType1的執行個體,及操作其attribute1屬性的過程(其中“//->”後面展示了提示結果)。
var t1 =NewClassType1(); t1.attribute1+= 3; alert("t1.attribute1= " + t1.attribute1); //->t1.attribute= 6
建構函式方式建立class使用關鍵字this來建立類中屬性或方法。使用new關鍵字來擷取執行個體。
//建構函式方式,用new擷取特定類型的對象執行個體 functionNewClassType2(){ this.attribute2= 2; }; vart2 = new NewClassType2(); t2.attribute2+= 6 alert("t2.attribute2= " + t2.attribute2); //->t2.attribute2= 8
原型方式則利用了javascript物件導向中一個很獨特的性質——類型的原型(prototype),它可以動態擴充相應類型的屬性和方法。
//原型方式,利用javascript對象的prototype屬性 functionNewClassType3(){}; NewClassType3.prototype.attribute3= 1; Vart3 = new NewClassType3(); t3.attribute3+= 2; alert("t3.attribute3= " + t3.attribute3); //->t3.attribute3= 3
原型方式中的原型概念需要理解一下。從上面幾個例子中可以看出javascript的類型是以函數形式定義的,其名稱為類型名稱。而javascript每個類型都具備一個prototype屬性,這個屬性返回物件類型原型的引用,它是一個對象。我們可以將原型看做是一個參照,當我們建立一個類型的執行個體時,瀏覽器會自動將原型(prototype)的內容(屬性和方法)附加到object上。此外,javascript對象是動態,故而原型也是動態。我們對原型(prototype)進行擴充,將改變類型的原型,這種改變將直接作用到這個原型建立的所有對象上。
下面代碼展現了擴充原型的屬性(要進行初始化操作)和方法。
/* * 使用建構函式形式建立類型 */ functionType1(name){ this.name= name; } //new一個Type1執行個體 varobj1 = new Type1("chwd"); alert(obj1.name); //->chwd alert(obj1.age); //->undefined //對Type1的原型中增加一個屬性age,記得要賦值 Type1.prototype.age; alert(obj1.age); //->undefined Type1.prototype.age= 18; alert(obj1.age); //->18 obj1.age+= 8; alert(obj1.age); //->21 //對類型Type1的原型增加一個方法 Type1.prototype.showYourNameAndAge= function(name){ this.name= name; alert("myname is " + name + " and my age is " + this.age); }; //對象obj1調用showYourNameAndAge方法 obj1.showYourNameAndAge("cweid"); //->myname is cweid and my age is 26
上文展示了對一個類型的原型進行擴充後,之前建立的此類型的執行個體也相應發生了變化。既然原型是一個對象,那能否對類型的原型進行複製,以期改變類型的整個原型結構呢?是可以的,如下代碼所示。
/* * 使用建構函式形式建立類型 */ functionType1(name){ this.name= name; } //new一個Type1執行個體 varobj1 = new Type1("chwd"); alert(obj1.name); //->chwd //對類型Type1的原型增加一個方法 Type1.prototype.showYourNameAndAge= function(name){ this.name= name; alert("myname is " + name ); }; //對象obj1調用showYourNameAndAge方法 obj1.showYourNameAndAge("chenwd"); //->myname is chenwd /* * 再建立一個類型Type2 */ functionType2(){ this.age= 26; } //new一個Type2執行個體 varobj2 = new Type2("chweidong"); alert(obj2.name); //->undefined //對象obj2調用showYourNameAndAge方法// obj2.showYourNameAndAge("cwdong"); //->undefined //將Type2的原型設定為Type1的原型 Type2.prototype =Type1.prototype; //再次顯示obj2的name alert(obj2.name); //->undefined varobj3 = new Type2("chenweid"); alert(obj3.name); //->undefined //將Type2的原型設定為對象obj1 Type2.prototype= obj1; //第三次顯示obj2的name alert(obj2.name); //->undefined alert(obj2.age); //->26 varobj4 = new Type2("hahahaha"); alert(obj4.name); //->chenwd alert(obj4.age); //->26 obj4.showYourNameAndAge("chenweidong"); //->myname is chenweidong
上文代碼說明對類型的prototype屬性賦的值必須為對象,且不能將另一個類型的原型做為值。這種賦值方式雖然修改了prototype,但對並不影響之前建立的執行個體(需要重建立立執行個體,如obj4),不過從obj4的運行結果可以看出這種賦值方式是對原有類型擴充而非覆蓋。
在上述javascript建立類型和利用prototype屬性進行擴充的基礎上,我們可以簡單瞭解到prototype.js這個javascript架構的實現原理。prototype.js是對標準javascript庫的擴充。它擴充了Object、Number、Function、String等類型,並且定義了一些新對象和類型,如Prototype對象、Class對象和Ajax對象等等,同時封裝了javaScript的Ajax應用。Prototype.js的這些擴充極大的方便了開發人員建立高互動性的web2.0應用。
此架構大多是對原生對象功能的擴充,但它卻是其他javascript架構的基礎,可以說是鼻祖級的架構。下面體會下prototype.js對javascript擴充後是如何建立類型的。
在prototype.js中增加了Class對象,其方法create能夠建立新類型,其文法為:
create([superclass][, methods...])
1.6版本後Class.create方法有兩個參數,第一個參數指定待建立類的父類,如果沒有父類對象傳入,則預設對象為Object。以下代碼展示了Class.create的用法。
//createclass---Animal ,it can speak varAnimal = Class.create({ initialize:function(name,sound){ this.name= name; this.sound= sound; }, speak:function(){ alert(this.name+ " says: " + this.sound + "!"); } }); //體驗initialize方法 //varanimal = new Animal("animal1" , "bark"); //animal.speak(); //->animal1says: bark! //建立子類 varDog = Class.create( Animal, { initialize:function($super,name){ $super(name,"hahah"); } } ); vardog1 = new Dog("dog1","bark,bark"); dog1.speak(); //->dog1says: hahah!
上文展示的是prototype1.6及以後版本的建立方法,而在1.6之前採用的javascript 的prototype屬性以及prototype.js擴充的Object.extend方法。它們之間大同小異,1.6以後的一大句即可將類或子類(繼承)建立完畢,而1.6之前需要兩句。代碼如下所示:
<head><metahttp-equiv="Content-Type" content="text/html;charset=gb2312" /><title>1.6以前建立類型的方式</title><scriptsrc="prototype-1.5.1.2.js"></script></head><script> //createclass---Animal ,it can speak varAnimal = Class.create(); Animal.prototype= { initialize:function(name,sound){ this.name= name; this.sound= sound; }, speak:function(){ alert(this.name+ " says: " + this.sound + "!"); } }; //體驗initialize方法 varanimal = new Animal("animal1" , "bark"); animal.speak(); //->animal1says: bark! //建立子類 varDog = Class.create(); Dog.prototype= Object.extend( newAnimal(), { initialize:function(name){ this.name= name; this.sound= "hahah"; } } ); vardog1 = new Dog("dog1","bark,bark"); dog1.speak(); //->dog1says: hahah! </script>
至此本文簡單陳述了javascript進階應用程式中的類型建立方式,及其prototype屬性的部分性質,並由此屬性簡單介紹了prototype.js及其建立和類繼承的方式。揭示出prototype.js是鼻祖級javascript架構,這類架構在工作生產中能極大程度的提高開發效率。