javascript中提供了通過Object建構函式或對象字面量方式來建立單個的對象,當我們想要建立很多個物件的時候,簡單的通過這兩種方法就會產生大量的重複。在此,我總結了幾種建立對象的模式。本文是在我閱讀《javascript進階程式設計》後總結而來。 1.原廠模式這種模式通過用函數來減少代碼重複,利用函數的參數作為介面,與對象的屬性與方法對接。 複製代碼function createfactory(name,age){ var obj = new Object(); obj.name = name; obj.age = age; return obj;}var test1 = createfactory('aaa',18);var test2 = createfactory('bbb',50);複製代碼這樣就完成了簡單的代碼複用,實現了代碼重複,但是無法確定所建立對象的類型。 建構函式模式我們都知道Object,Array等原生的建構函式可以用來建立對象。建構函式模式和此類似,通過自訂建立建構函式,來建立新類型的對象。 複製代碼function Createfunction(name,age,){ this.name = name; this. age = gae; this.sayname = function(){ alert(this.name); }}var test1 = new Createfunction('aaa',20);var test2 = new Createfunction('bbb',50);複製代碼按照慣例,建構函式應以一個大寫字母開頭。這種模式可以將新對象的類型確定下來。然後這種模式依舊存在問題,test1和test2兩個執行個體中都有 sayname方法,在javascript中函數就是對象,因此在建立test1和test2的同時也執行個體化了兩次函數對象,相當於這樣: 複製代碼###原型模式每個函數都有一個prototype屬性,指向它的原型對象。原型對象可以讓所有對象執行個體共用其中的屬性和方法。看下面的例子。```javascriptfunction Cf(){}Cf.prototype.name = "aaa";Cf.prototype.age = 29;Cf.prototype.sayname = function(){ alert(this.name); }var test1 = new Createfunction();var test2 = new Createfunction();複製代碼上面這種方法通過將屬性和方法添加到了建構函式的原型對象中,這樣新對象的所有執行個體會共用這些屬性和方法。為了進一步減少代碼量,有人提出了重寫原型對象的方法。看下面的例子。 複製代碼function Cf(){}Cf.prototype = { name = "aaa"; age = 29; sayname = function(){ alert(this.name); }}var test1 = new Createfunction();var test2 = new Createfunction();複製代碼這種方法通過重寫原型對象進一步減少代碼重複,然而這樣的寫法帶來了新的問題。在簡單的通過原型模式建立對象時,原型對象的動態變化會即時的反應 在執行個體中,因為執行個體中的[[Prototype]]屬性是指向原型對象的,這樣對於調用屬性和方法的向上搜尋過程,會搜尋到原型對象中的屬性和方法。而當 先執行個體化一個對象後,再重寫原型對象,執行個體中的[[Prototype]]不再指向新的原型對象,因而導致在調用的過程中無法向上搜尋到新的原型對象,所 以在使用重寫原型對象方法的時候,一定要先重寫對象,再建立執行個體。原型對象模式依舊存在缺點,雖然它省略了為函數傳參這一環節,但是執行個體預設情況下都取得相同的屬性值。此外對於包含參考型別的屬性來說,當對執行個體屬性修改會導致原型對象中屬性的同步變化。這樣,這種變化也就即時的反應在了所有的執行個體中。顯然這不是我們想要的結果。聯絡前面說的建構函式模式,我們可以通過組合使用建構函式模式和原型模式來解決這一問題。 複製代碼function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype = { constructor: Person, sayName : function () { alert(this.name); } }; var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");複製代碼在建構函式中定義執行個體屬性,在原型模式中定義方法和共用的屬性。這樣,每個執行個體都有自己的執行個體屬性的副本,同時也有共用的屬性和方法,節省了記憶體,也可以通過傳參來定義執行個體屬性。 動態原型模式動態原型模式其實相當於原型模式的一個變種,將所有的資訊都封裝在建構函式中,僅在必要的情況下初始化原型對象。 複製代碼function Person(name, age, job){ //properties this.name = name; this.age = age; this.job = job; //methods if (typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; } } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName();複製代碼在這個建構函式中通過判斷屬性是否存在來決定是否對原型對象初始化。這樣只有在第一次執行個體化對象時才會對原型對象初始化,可以說是十分的完美了。 寄生建構函式模式當我們想為一個已經存在的建構函式建立一個具有額外方法的建構函式,由於不能重寫存在的建構函式,這時就可以使用這種模式了。看例子。 複製代碼 function SpecialArray(){ //create the array var values = new Array(); //add the values values.push.apply(values, arguments); //assign the method values.toPipedString = function(){ return this.join("|"); }; //return it return values; } var colors = new SpecialArray("red", "blue", "green");複製代碼這個例子中,建立了一個具有額外方法的數組,具有額外的特殊方法,在不修改數組建構函式的前提下,建立了一個新的建構函式。不過寄生建構函式模式返回的對象與建構函式的原型對象沒有關係。