Javascript 從名字上聽起來跟JAVA有著聯絡,但其實卻是兩門根本不同的語言。在Java中定義類是輕而易舉事情,但是要在JavaScript中定義一個好的對象卻是要花點心思。本文介紹幾種方法,並比較他們的優劣。
1、 工廠方式
這種方式可能是我們最容易想到的了,見代碼:
var employee = new Object;
employee.name = "Tim";
employee.age = 24;
employee.getName = function(){
alert(this.name);
}
這段代碼建立了一個employee 對象,並設定了他的幾個屬性:name ,age 。而getName這個屬性其實是一個指標,他指向一個函數,因而成為該對象的一個方法。使用這種方式可以建立一個對象,但是如果我們需要建立多個對象呢?總不能類似的再敲幾片吧。我們把他封裝一下,寫出一個方法:
function createEmployee(names,ages){
var employee = new Object;
employee.name = names;
employee.age = ages;
employee.getName = function(){
alert(this.name);
}
return employee;
}
var employee1 = createEmployee("Tim",24);
var employee2 = createEmployee("Tom",22);
employee1.getName();
employee2.getName();
但是你會發現其實我們在建立兩個對象的時候,建立了兩個getName()方法,其實每個對象共用一個getName()就可以了,浪費記憶體空間。
2、建構函式方式
function Employee( names,ages ){
this.name = names;
this.age = ages;
this.getName= function(){
alert(this.name);
}
}
var employee1 = new Employee("Tim",24);
var employee2 = new Employee("Tom",22);
employee1.getName();
employee2.getName();
這種方式不像第一種方式需要在函數內部建立對象,而是使用了this關鍵字。然後用new來建立對象,這跟Java的非常相像了。但是他同樣跟原廠模式一樣會重複產生函數。
3、原型方式
function employee(){
}
employee.prototype.name = "Tim";
employee.prototype.age = 24;
employee.prototype.getName = function (){
alert( this.name );
};
var employee1 = new employee();
var employee2 = new employee();
使用這種方式很好的解決了前兩種方法的問題,但是新的問題有來了,如果這樣:
function employee(){
}
employee.prototype.name = "Tim";
employee.prototype.age = 24;
employee.prototype.friends = new Array( "Jack", "Tom" );
employee.prototype.getName = function (){
alert( this.name );
};
var employee1 = new employee();
var employee2 = new employee();
employee1.friends.push( "Tina" );
alert(employee1.friends);
alert(employee2.friends);
這兩個對象都是輸出“Jack,Tom,Tina”。這是因為friends是指向Array對象的指標,兩個對象都指向同一個Array,因而修改一個對象的friends,另一個對象也是修改。這肯定不是我們想要的。
4、混合建構函式/原型模式
function Employee( names,ages ){
this.name = names;
this.age = ages;
this.friends = new Array( "Jack", "Tom" );
}
Employee.prototype.getName = function (){
alert( this.name );
};
var employee1 = new Employee("Tim",24);
var employee2 = new Employee("Tom",22);
employee1.friends.push( "Tina" );
alert(employee1.friends); //輸出“Jack,Tom,Tina”
alert(employee2.friends); //輸出“Jack,Tom”
結合構造和原型兩種方式,徹底解決了上訴兩種情況。他只建立一個getName執行個體,不會浪費記憶體,而且在修改friends屬性時,也不會修改其他對象的friends屬性。
5、動態原型方法
function Employee( names,ages ){
this.name = names;
this.age = ages;
this.friends = new Array( "Jack", "Tom" );
if( typeof Employee._initialized == "undefined" ){
Employee.prototype.getName = function(){
alert( this.name );
}
Employee._initialized = true;
}
}
使用這種方式,是不是覺得更像Java的CLASS編寫方式了?
總結:通過比較,明顯可以看出“建構函式/原型模式”和“動態原型”的優勢,建議編程時採用。