JavaScript中沒有類的概念,只有對象。
在JavaScript中定義對象可以採用以下幾種方式:
1.基於已有對象擴充其屬性和方法
2.工廠方式
3.構造函數方式
4.原型(“prototype”)方式
5.動態原型方式
一.基於已有對象擴充其屬性和方法
<script type="text/javascript">
var object = new Object();
object.name = "zhangsan";
object.sayName = function(name)
{
this.name = name;
alert(this.name);
}
object.sayName("lisi");
</script>
這種方式的弊端:這種對象的可複用性不強,如果需要使用多個對象,還需要重新擴展其屬性和方法。
二.工廠方式
function createObject()
{
var object = new Object();
object.username = "zhangsan";
object.password = "123";
object.get = function()
{
alert(this.username + ", " + this.password);
}
return object;
}
var object1 = createObject();
var object2 = createObject();
object1.get();
改進一:採用帶參數的構造方法:
function createObject(username, password)
{
var object = new Object();
object.username = username;
object.password = password;
object.get = function()
{
alert(this.username + ", " + this.password);
}
return object;
}
var object1 = createObject("zhangsan", "123");
object1.get();
改進二:讓多個對象共享函數對象
這樣,不用每個對象都生成一個函數對象。
function get()
{
alert(this.username + ", " + this.password);
}
//函數對象只有一份
function createObject(username, password)
{
var object = new Object();
object.username = username;
object.password = password;
object.get = get; //每一個對象的函數對象都指向同一個函數對象
return object;
}
var object = createObject("zhangsan", "123");
var object2 = createObject("lisi", "456");
object.get();
object2.get();
優點:讓一個函數對象被多個對象所共享,而不是每一個對象擁有一個函數對象。
缺點:對象和它的方法定義分開了,可能會造成誤解和誤用。
三.構造函數方式
構造函數的定義方法其實和普通的自定義函數相同。
function Person()
{
//在執行第一行代碼前,js引擎會爲我們生成一個對象
this.username = "zhangsan";
this.password = "123";
this.getInfo = function()
{
alert(this.username + ", " + this.password);
}
//此處有一個隱藏的return語句,用於將之前生成的對象返回
//只有在後面用new的情況下,纔會出現註釋所述的這兩點情況
}
//生成對象
var person = new Person();//用了new
person.getInfo();
改進版:加上參數:
function Person(username, password)
{
this.username = username;
this.password = password;
this.getInfo = function()
{
alert(this.username + ", " + this.password);
}
}
var person = new Person("zhangsan", "123");
person.getInfo();
四.原型(“prototype”)方式
例子:
function Person()
{
}
Person.prototype.username = "zhangsan";
Person.prototype.password = "123";
Person.prototype.getInfo = function()
{
alert(this.username + ", " + this.password);
}
var person = new Person();
var person2 = new Person();
person.username = "lisi";
person.getInfo();
person2.getInfo();
使用原型存在的缺點:
1.不能傳參數;
2.有可能會導致程序錯誤。
如果使用原型方式來定義對象,那麼生成的所有對象會共享原型中的屬性,這樣一個對象改變了該屬性也會反映到其他對象當中。
單純使用原型方式定義對象無法在構造函數中爲屬性賦初值,只能在對象生成後再去改變屬性值。
比如,username改爲數組後:
function Person()
{
}
Person.prototype.username = new Array();
Person.prototype.password = "123";
Person.prototype.getInfo = function()
{
alert(this.username + ", " + this.password);
}
var person = new Person();
var person2 = new Person();
person.username.push("zhangsan");
person.username.push("lisi");
person.password = "456";
person.getInfo(); //輸出:zhangsan,lisi, 456
person2.getInfo(); //輸出:zhangsan,lisi, 123
//雖然沒有對person2對象進行修改,但是它的name和person是一樣的,即爲zhangsan,lisi
這是因爲使用原型方式,person和person2指向的是同一個原型,即對應了同樣的屬性對象。
對於引用類型(比如數組),兩個對象指向了同一個引用,所以對一個所做的更改會影響另一個。
而對於字符串(字面常量值),重新賦值之後就指向了另一個引用,所以二者的修改互不影響。
對原型方式的改進:
使用原型+構造函數方式來定義對象,對象之間的屬性互不干擾,各個對象間共享同一個方法。
<script type="text/javascript">
//使用原型+構造函數方式來定義對象
function Person()
{
this.username = new Array();
this.password = "123";
}
Person.prototype.getInfo = function()
{
alert(this.username + ", " + this.password);
}
var p = new Person();
var p2 = new Person();
p.username.push("zhangsan");
p2.username.push("lisi");
p.getInfo();
p2.getInfo();
</script>
五.動態原型方式
在構造函數中通過標誌量讓所有對象共享一個方法,而每個對象擁有自己的屬性。
<script type="text/javascript">
function Person()
{
this.username = "zhangsan";
this.password = "123";
if(typeof Person.flag == "undefined")
{
//此塊代碼應該只在第一次調用的時候執行
alert("invoked");
Person.prototype.getInfo = function()
{
//這個方法定義在原型中,會被每一個對象所共同擁有
alert(this.username + ", " + this.password);
}
Person.flag = true;//第一次定義完之後,之後的對象就不需要再進來這塊代碼了
}
}
var p = new Person();
var p2 = new Person();
p.getInfo();
p2.getInfo();
</script>
參考資料
聖思園張龍老師Java Web視頻教程。
W3School JavaScript教程:http://www.w3school.com.cn/js/index.asp
英文版:http://www.w3schools.com/js/default.asp