js的對像編程
定義類或對象http://www.iwms.net/n1982c17.aspx
定義類或對象
雖然ECMAScript越來越正規化了,但創建對象的方法卻被置之不理。在高級的編程語言(如C#)中,創建對象的方法被明確的定義了。所以不會有太大的分歧。但在腳本語言中創建對象的方法就是多種多樣了。
4.1 工廠方式
由于對象的屬性可在對象創建后動態定義,所以許多開發者都在初次引入JavaScript時編寫類似下面的代碼:
Var oCar=new Object();
oCar.color="red";
oCar.doors=4;
oCar.mpg=23;
oCar.showColor=function(){alert(this.color);};
在這段代碼中,創建對象car。然后給它設置幾個屬性:它的顏色是紅色,有四個門,每加侖油23英里。最后一個屬性是指向函數的指針,意味著該屬性其實是個方法。執行這段代碼后,就可以使用對象car了。可是要創建多個car實例就麻煩了。
要解決此問題,開發者可以創建并返回特定類型的對象的工廠函數。例如,函數CreateCar()可用于封裝前面列出的創建car對象的操作:
Function createCar()
{
Var oTempCar=new Object();
oTempCar.color="red";
oTempCar.doors=4;
oTempCar.mpg=23;
oTempCar.showColor=function(){alert(this.color)};
return oTempCar;
}
Var oCar1=createCar();
Var oCar2=createCar();
這里,前面的所有代碼都包含在createCar()函數中,此外還有一行額外的代碼,返回Car對象作為函數值。調用此函數時,將創建新對象,并賦予它 所有必要的屬性,復制出一個前面說明的car對象。使用該方法,可以容易地創建car對象的兩個版本,他們的屬性完全一樣。當然,還可以修改 creatCar()函數,給它傳遞各個屬性的默認值,而不是賦予屬性默認值:
Function createCar(sColor,iDoors,iMpg)
{
Var oTempCar=new Object();
oTempCar.color= sColor;
oTempCar.doors= iDoors;
oTempCar.mpg= iMpg;
oTempCar.showColor=function(){alert(this.color)};
return oTempCar;
}
Var oCar1=createCar("red",4,23);
Var oCar2=createCar("blue",2,26);
oCar1.showColor(); // 輸出"red"
oCar2.showColor(); // 輸出"blue"
給createCar()函數加上參數,即可為要創建的car對象的color、doors和mpg屬性賦值。使這兩個對象具有相同的屬性,卻有不同的屬 性值。但這里有個問題:每次調用函數createCar(),都要創建新函數showColor(),意味著每個對象都有自己的showColor()版 本。事實上,每個對象用的都是同一段代碼。這樣的定義方法還有一個如下的變形:
Function Car(sColor,iDoors,iMpg)
{
this.color= sColor;
this.doors= iDoors;
this.mpg= iMpg;
this.showColor=function(){alert(this.color)};
}
Var oCar1=new Car("red",4,23);
Var oCar2=new Car("blue",2,26);
oCar1.showColor(); // 輸出"red"
oCar2.showColor(); // 輸出"blue"
這個方法和上一個方法有個一樣的缺陷:重復的創建了showColor()函數。為了解決這個缺陷我們可以用下面的方法。
4.2 原型方式
該方法利用了對象的Prototype屬性。用空構造函數來設置類名,然后所有的屬性和方法都被直接賦予prototype屬性:
Function Car()
{}
Car.prototype.color="red";
Car.prototype.doors=4;
Car.prototype.mpg=23;
Car.prototype.showColor=function(){alert(this.color)};
Var oCar1=new Car();
Var oCar2=new Car();
使用這個方法可以解決重復創建showColor()函數,但又會有新的問題,考慮下面的例子:
Function Car()
{}
Car.prototype.color="red";
Car.prototype.doors=4;
Car.prototype.mpg=23;
Car.prototype.drivers=new Array("Mike","Sue");
Car.prototype.showColor=function(){alert(this.color)};
Var oCar1=new Car();
Var oCar2=new Car();
oCar1.drivers.push("Matt");
alert(oCar1.drivers); // 輸出"Mike,Sue,Matt"
alert(oCar2.drivers); // 輸出"Mike,Sue,Matt"
這里,屬性drivers是指向Array對象的指針。改變指針指向的內容,所有的實例都會改變。看來這種方法也不可取
4.3 混合方式
這種方式就是用構造函數定義對象的所有非函數屬性,用原型方式定義對象的函數屬性(方法)。結果所有的函數只創建一次,而每個對象都具有自己的對象屬性實例。
Function Car(sColor,iDoors,iMpg)
{
this.color= sColor;
this.doors= iDoors;
this.mpg= iMpg;
Car.drivers=new Array("Mike","Sue");
}
Car.prototype.showColor=function(){alert(this.color)};
Var oCar1=new Car("red",4,23);
Var oCar2=new Car("blue",3,25);
oCar1.drivers.push("Matt");
alert(oCar1.drivers); // 輸出"Mike,Sue,Matt"
alert(oCar2.drivers); // 輸出"Mike,Sue"
這種方式是ECMAScript主要采用的方式,它具有其他方式的特性,卻沒有它們的缺陷。在實際編程中應用的也是最多了。
另外還有JSON創建方式。其創建的方式如下:
var Car =
{
color: "red",
doors: 4,
mpg: 23,
drivers: [{name: "Mike", age: 20, Married: false}, {name: "Sue", age: 30, Marred: true}],
showColor: function() {alert(this.color)}
};
這種創建對象的方式也比較優雅。可作為Ajax返回的文本,然后用eval()函數將其還原成一個對象。著名的腳本框架JQuery就有專門接收返回文本為JSON對象的異步方法。