本文轉載自: http://www.phpfuns.com/scripts/javascript/five-method-define-javascript-object.shtml
JavaScript中定義對象的5種方式(JavaScript中沒有類的概念,只有對象)
i)基於已有對象擴充其屬性和方法
var object = new Object();object.name = "zhangsan"; // 添加name屬性object.sayName = function(name){//添加sayName方法 this.name = name; alert(this.name);};object.sayName("kyle");//調用sayName方法,name屬性被修改為kyle,瀏覽器將列印kyle
最簡單的一種方式,使用起來並不方便,適合於臨時需要一個對象。
ii)工廠方式建立對象
不帶參數的Factory 方法:
//Factory 方法function createObject(){ var object = new Object(); //建立一個對象 object.name = "zhangsan"; //為該對象添加一個name屬性 object.password = "123"; //為該對象添加一個password屬性 object.get = function(){ //為該對象添加一個get方法 alert(this.name+","+this.password); }; return object; //返回該對象}var object1 = createObject(); //調用createObjectFactory 方法建立對象object1var object2 = createObject(); //調用createObjectFactory 方法建立對象object2object1.get(); //調用對象get方法object2.get(); //調用對象get方法
帶參數的Factory 方法:
function createObject(name, password) { var object = new Object(); object.name = name; object.password = password; object.get = function() { alert(this.name + "," + this.password); }; return object;}var object1 = createObject("zhangsan", "123");var object2 = createObject("lisi", "456");object1.get();object2.get();
上面兩種不帶參數和帶參數的Factory 方法缺點:
每建立一個對象,記憶體中就建立一個get方法,比較浪費記憶體,且影響效能。而我們的期望是,建立兩個不同的對象,它們的屬性是不一樣的,但方法是共用的。所以接下來我們需要改進createObjectFactory 方法。
改進的Factory 方法:
// 把get()放在外面實現共用function get() { alert(this.name + "," + this.password);}
function createObject(name, password) { var object = new Object(); object.name = name; object.password = password; object.get = get; return object;}var object1 = createObject("zhangsan", "123");var object2 = createObject("lisi", "456");object1.get();object2.get();
將get方法定義在createObject函數外面,這樣每建立一個對象,get方法都是共用的。讓一個函數對象被多個對象所共用,而不是每一個對象都擁有一個函數對象。
iii)建構函式方式建立對象
不帶參數的建構函式
function Person(){ //在執行第一行代碼前,js引擎會為我們產生一個對象 this.name = "zhangsan"; this.password = "123"; this.getInfo = function(){ alert(this.name+","+this.password); }; //此處有一個隱含的return語句,用於將之前產生的對象返回(也是跟工廠方式不一樣的地方)}var p1 = new Person(); p1.getInfo();
帶參數的建構函式
function Person(name, password) { this.name = name; this.password = password; this.getInfo = function() { alert(this.name + "," + this.password); };}var p1 = new Person("zhangsan", "123");var p2 = new Person("lisi", "456");p1.getInfo();p2.getInfo();
iv)原型(prototype)方式建立對象
prototype是Object對象裡面的一個屬性,
function Person() {}Person.prototype.name = "zhangsan";Person.prototype.password = "123";Person.prototype.getInfo = function() { alert(this.name + "," + this.password);};var p1 = new Person();var p2 = new Person();p1.name = "kyle";// 對象產生之後再去改變屬性 p1.getInfo(); p2.getInfo();
單純地使用原型方式有兩個問題:第一,你無法在建構函式中為屬性賦初值,只能在對象產生之後再去改變屬性值。
function Person() {}Person.prototype.name = new Array();Person.prototype.password = "123";Person.prototype.getInfo = function() { alert(this.name + "," + this.password);};var p1 = new Person();var p2 = new Person();p1.name.push("zhangsan");p1.name.push("lisi");p1.password = "456";p1.getInfo();p2.getInfo();
瀏覽器將會列印:zhangsan,lisi,456和zhangsan,lisi,123.
如果使用原型方式建立對象,那麼產生的所有對象會共用原型中的屬性,這樣一個對象改變了該屬性也會反應到其他對象當中。所以單純地使用原型方式是不行的,還需要結合其他方式。接下來我們會繼續介紹。
使用原型+建構函式方式來定義對象
function Person() { this.name = new Array(); this.password = "123";}Person.prototype.getInfo = function() { alert(this.name + "," + this.password);};var p1 = new Person();var p2 = new Person();p1.name.push("zhangsan");p2.name.push("lisi");p1.getInfo();p2.getInfo();
使用原型+建構函式方式來定義對象,對象之間的屬性互不干擾,各個對象間共用同一個方法,這是一種比較好的方式。
v)動態原型方式
function Person() { this.name = "zhangsan"; this.password = "123"; if (typeof Person.flag == "undefined") { alert("invoked"); Person.prototype.getInfo = function() { alert(this.name + "," + this.password); }; Person.flag = true; }}var p1 = new Person();var p2 = new Person();p1.getInfo();p2.getInfo();
在動態原型方式中,在建構函式中通過標誌量讓所有對象共用一個方法,而每個對象擁有自己的屬性。上面代碼在第一次建立對象時,首先通過一個判斷語 句,看flag屬性是否已經定義,若沒有定義,則通過原型方式添加getInfo方法,然後將flag設定為true,那麼當第二次建立對象時,if語句 判斷為假,跳過執行。這樣就達到了我們所期望的結果,建立的對象屬性是互不干擾的,而對象的方法是共用的。