ECMAScript創建對象1 —— Object()、工廠模式、構造函數模式

使用Object構造函數或對象字面量

在JavaScript中,我們可以很輕鬆的通過如下方式創建一個對象

var obj1 = new Object();
obj1.proto1 = 'proto1'; // 使用Object構造函數

var obj2 = {
    proto2: 'proto2'
} // 使用對象字面量

這兩種方式都能很直觀簡單地幫助我們創建一個新的對象,但這兩種方法也有很明顯的缺點:每一個對象都需要我們不停地給它添加屬性,即使是創建兩個具有相同屬性的對象,這會產生大量的重複代碼。

工廠模式

工廠模式應該是最廣爲人知的一種設計模式了,它抽象了創建對象的具體過程,解決了重複代碼的問題。由於ECMAScript中沒有類的概念,所以只能使用函數來封裝創建對象的細節。如:

function createObj (name, age) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    return obj
}

var obj1 = createObj('a', 10); // {name: 'a', age: 10}
var obj2 = createObj('b', 11); // {name: 'b', age: 11}

工廠模式雖然解決了重複代碼的問題,但它創建的對象的類型都是Object:

obj1 instanceof createObj  // false
obj1 instanceof Object  // true

構造函數模式

我們可以使用Array、Object等構造函數來創建我們需要的對象,我們也可以自定義一個構造函數來創建一個自定義類型的對象。構造函數並不是什麼特殊的函數,任何函數使用new關鍵字調用都能作爲構造函數,只是有一個慣例,構造函數的函數名始終以大寫字母開頭

相比於工廠模式,構造函數的代碼有了幾點不同:

  • 沒有顯式地創建的對象(var obj = new Object() 語句)
  • 將需要的屬性和方法都賦給了this對象
  • 沒有return

上面的代碼可以重寫如下:

function CreateObj (name, age) {
    this.name = name;
    this.age = age;
    this.sayName = function () {
        console.log(this.name);
    }
}

var obj1 = new CreateObj('a', 10); // {name: 'a', age: 10}
var obj2 = new CreateObj('b', 11); // {name: 'b', age: 11}
CreateObj('c', 12); // {name: 'c', age: 12}
obj1 instanceof CreateObj // true
obj1 instanceof Object // true
obj1.sayName == obj2.sayName // false

構造函數讓每個實例都擁有了特定的類型,但這種模式也有缺點:

由於ECMAScript中函數也是對象,所以對於不同的CreateObj實例,它們的sayName屬性就是互不相等但功能完全相同的函數對象,實在沒有必要;況且,既然有了this的存在,sayName屬性完全可以採用下面的寫法:

function CreateObj (name, age) {
    this.name = name;
    this.age = age;
    this.sayName = sayName;
}
function sayName = function () {
    console.log(this.name);
}

在全局中創建的sayName函數能夠解決創建多個功能相同的函數的問題,但是它的問題在於只有CreateObj實例能正確使用它,這樣就失去了全局函數的意義,這也在對象只需要一個方法的情況下,如果需要很多方法,就需要創建很多的只能特定對象調用的全局函數,毫無封裝性可言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章