標籤:red 關係 參考 數組 class argument 基礎上 html 語句
一、原廠模式1. 程式碼範例
function person(name, age) { var p = new object(); p.name = name; p.age = age; p.sayName = function() { console.log(this.name); }; return p;}var person1 = person(‘Bonnie‘, 26);var person2 = person(‘Summer‘, 24);
2. 優點
解決了建立多個相似對象的問題。
3. 缺點
沒有解決對象識別的問題。
二、 建構函式模式1. 程式碼範例
function Person(name, age) { this.name = name; this.age = age; this.sayName = function() { console.log(this.name); }}var person1 = new Person(‘Bonnie‘, 26);var person2 = new Person(‘Summer‘, 24);
牢記:建構函式在不傳回值的情況下,預設會返回新對象的執行個體(建構函式模式)。 如果在建構函式內部末尾添加一個return語句,可以重寫調用建構函式時返回的值(寄生建構函式模式)。
2.優點
建立自訂的建構函式意味著可以將它的樣本標誌為一種特定的類型(執行person1 instanceof Person為true)。這就是它比原廠模式更勝一籌的地方。
3.缺點
每個方法都要在每個執行個體上建立一遍。也就是說,使用建構函式模式建立的每個執行個體都包含著各自專屬的同名函數。然而,建立兩個完成同樣任務的同名函數並沒有必要。
可以像這樣使建構函式建立的每個執行個體都引用一個方法:
function Person(name, age) { this.name = name; this.age = age; this.sayName = sayName;}function sayName() { console.log(this.name);}
但是這樣帶來的問題是被建構函式的不同執行個體共同引用的這個方法存在於全域範圍中,這一方面破壞了全域範圍,另一方面也破壞了該自訂類型的封裝性。
三、 原型模式1. 程式碼範例
function Person() {}Person.prototype.name = "Bonnie";Person.prototype.age = 26;Person.prototype.sayName = function() { console.log(this.name)}var person1 = new Person();var person2 = new Person();
2. 優點
可以讓所有對象執行個體共用它所包含的屬性和方法。
3. 缺點
首先,它省略了為建構函式傳遞初始化參數這一環節,這樣所有執行個體預設都會取得相同的屬性值。
更嚴重的是,其共用的本質對於參考型別的屬性值(如數組)是非常不適合的:對於修改一個執行個體上參考型別的屬性值也會修改另一個執行個體上的這個屬性值。不過,其共用本質對於函數非常合適,因為方法本來就是共用的。而其對於基本值的屬性也比較合適,因為可以通過在執行個體上添加同名的屬性名稱來覆蓋原型中的屬性。
詳見我的另一篇部落格《原型與原型鏈》 的"一、建立對象的重要模式:原型模式"。
四、 組合使用建構函式模式和原型模式1.程式碼範例
function Person(name, age) { this.name = name; this.age = age; this.friends = [‘Spring‘, ‘Huiyun‘];}Person.prototype.sayName = function() { console.log(this.name);}var person1 = person(‘Bonnie‘, 26);var person2 = person(‘Summer‘, 24);
2. 優點
執行個體屬性都在建構函式中實現,共用的屬性和方法在原型中定義,是使用最廣、認同度最高的一種建立自訂類型的方式。也是預設。
五、動態原型模式1. 程式碼範例
function Person(name, age) { this.name = name; this.age = age; if (typeof this.sayName != ‘function‘) { Person.prototype.sayName = function() { console.log(this.name); } }}
2. 優點
只有在某方法不存在的情況下,才將該方法添加到原型上。添加到原型上這段代碼只會在初次調用建構函式時才會執行。對原型所做的修改會立刻反映到所有執行個體中。
注意:不能使用對象字面量重寫原型,因為如果已經建立了執行個體,那麼重寫原型會切斷現有執行個體和新原型之間的聯絡。
六、寄生建構函式模式1. 程式碼範例
function Person(name, age) { var o = new Object(); o.name = name; o.age = age; o.sayName = function() { console.log(this.sayName); } return o;}var person1 = new Person(‘Bonnie‘, 26);
除了使用new操作符並把封裝的函數叫做建構函式之外,該模式跟原廠模式是一模一樣的。建構函式在不傳回值的情況下預設返回新對象執行個體。而通過在建構函式內部末尾添加return語句,可以重寫調用建構函式時返回的值。
2. 優點
該模式適於為特殊對象(如Array)建立具有新屬性、新方法的執行個體。也就是說適於在某些已有的特殊類型(如Array)的基礎上建立新的特殊類型(如SpecialArray)。
例如可以在Array的基礎上,建立具有額外方法的數組:
function SpecialArray() { var o = new Array(); o.push.apply(o, arguments); o.getPipedStr = function() { return this.join(‘|‘); } return o;}var colors = new SpecialArray(‘red‘, ‘blue‘, ‘green‘);console.log(colors);// ["red", "blue", "green", getPipedStr: ?]console.log(colors.getPipedStr);//"red|blue|green"
3. 缺點
該模式返回的對象與建構函式以及建構函式的原型之間毫無關係。也就是說,該模式返回的對象與在建構函式外部超級多個物件沒什麼不同。所以建構函式所表示的類型並不是執行個體的類型。
以上例來說:
colors instanceof SpecialArray;// false
七、 穩妥建構函式模式1. 程式碼範例
function Person(name, age) { var o = new Object(); //私人變數 var job = ‘developer‘; o.sayName = function() { console.log(name); } o.sayJob = function() { console.log(job); } return o;}var person1 = new Person(‘Bonnie‘, 26);person.sayName()//‘Bonnie‘person.sayJob()//‘Job‘
該方式建立的對象,除了sayName、sayJob方法以外,沒有別的辦法訪問變數name、job。
2. 優點
該模式提供了固定的方法來訪問建構函式中的未經處理資料(建構函式參數、私人變數)。除提供的方法外,沒有其他辦法可以訪問其建構函式中的未經處理資料。這種安全性使得穩妥建構函式模式非常適合在某些安全執行環境(如ADsafe、Caja)下使用。
參考資料
《JavaScirpt進階程式設計》6.2
JavaScript建立對象的幾種重要模式