一、開篇
(以下文字一部分來自於整理的書籍內容,一部分則是總結自經驗)
眾所周之,JavaScript是物件導向的語言。JavaScript的對象有三種:本機物件、內建對象、自訂類的對象。
其中本機物件和內建對象都是獨立於宿主由ECMAScript實現的。這裡所說的本機物件和內建對象實際上跟.Net中的類的概念相似。本機物件和內建對象的區別在於本機物件在使用時要執行個體化,而內建對象就像所謂的靜態類,可以直接使用。
JS中的本機物件有:Object Function Array String Boolean Number Date RegExp
Error等;內建對象有:Global和Math
下面著重介紹一下自訂類的五種方式:
二、在JavaScript中自訂類
1、Factory 方法
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();
oCar1.showColor();
缺點:缺點很多,基本上不會用到
2、建構函式方法
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);
oCar1.showColor();
alert(oCar1 instanceof Car);
原理:我們所謂的類還是js的一個Function而已,在Function前面用new運算子的時候,會自動建立一個object執行個體,並且類裡面的this都指向這個object,在Function運行結束的時候,將this返回。所以其本質還是Factory 方法。
優點:看起來和更像一個類 聲明執行個體用new運算子
缺點:對象的函數會重複產生
3、原型方式
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();
oCar1.showColor();
alert(oCar1 instanceof Car);
原理:js中的prototype
優點:避免了函數的重複建立
缺點:沒有帶參數的建構函式 屬性如果是參考型別(比如Array),那麼一個對象的屬性改變,另外一個對象的同一個屬性也會跟著改變
4、建構函式/原型方式
function Car(sColor,iDoors,iMpg){
this.color = sColor;
this.doors = iDoors;
this.mpg = iMpg;
}
Car.prototype.showColor = function(){
alert(this.color);
}
var oCar1 = new Car("red",4,23);
oCar1.showColor();
alert(oCar1 instanceof Car);
優點:避免了函數的重複建立 並且避免了建構函式方法的參考型別屬性的缺點
缺點:方法在類的外邊定義的
5、動態原型方式
function Car(sColor,iDoors,iMpg){
this.color = sColor;
this.doors = iDoors;
this.mpg = iMpg;
if(typeof Car._initialized == "undefined"){
Car.prototype.showColor = function(){
alert(this.color);
}
Car._initialized = true;
}
}
var oCar1 = new Car("red",4,23);
oCar1.showColor();
alert(oCar1 instanceof Car);
原理:Car也可以有屬性的 通過_initialized這個標誌確保方法只被聲明一次
優點:避免了函數的重複建立 屬性和方法都寫在類的定義裡
缺點:
三、我所使用的類
1、關於私人變數:
JavaScript中,基本上沒法區分私人變數和公開變數,但是可以在命名上區分,一般習慣在私人變數的前後各加上兩個底線 this.__privatePropery__或者是在變數前加一個底線this._privateProperty。
2、從建構函式方法衍生
對於第二種方法——建構函式方法對於私人變數的處理卻有很大的優勢!它可以將私人變數做到與外部隔離。這種隔離是將私人變數和方法在類裡面用var來聲明,而共有的變數和方法用賦值給this。
例子如下:
function Car(sColor,iDoors,iMpg){
var self = this;
this.color = sColor;
this.doors = iDoors;
var mpg = iMpg;//私人變數
this.showCarInfo = function(){
alert(this.color);
alert(mpg);//不是this.mpg
}
var privateShowCarInfo = function(){
//這時只能訪問私人變數
//alert(this.color);//會出錯
alert(mpg);//可以訪問
//那怎麼才能訪問this.color呢?總不可能私人方法不能訪問公用屬性吧?
//在類裡面設定一個私人變數,讓他指向這個執行個體//第二行中var self = this;
alert(self.color);//調用成功//當然 公用方法也能訪問self
}
this.anotherShowCarInfo = function(){
privateShowCarInfo();
}
}
var oCar1 = new Car("red",4,23);
oCar1.showCarInfo();
oCar1.anotherShowCarInfo();
alert(oCar1 instanceof Car);
總之:this.方法能訪問this.屬性和var 變數
Var方法只能訪問var變數,需要藉助self變數來訪問this.屬性
這樣的話顯得更物件導向了,但是建構函式方法的老毛病還是沒有改掉,對象的函數還是會被重複建立,但是我相信在一般情況下這對效能構不成威脅的。
四、樣本下載
點此下載樣本