# 構造器模式
在面向對象編程中,構造器是一個當新建對象的內存被分配后,用來初始化該對象的一個特殊函數。在JavaScript中幾乎所有的東西都是對象,我們經常會對對象的構造器十分感興趣。
對象構造器是被用來創建特殊類型的對象的,首先它要準備使用的對象,其次在對象初次被創建時,通過接收參數,構造器要用來對成員的屬性和方法進行賦值。
## 對象創建
下面是我們創建對象的三種基本方式:
下面的每一種都會創建一個新的對象:
~~~
var newObject = {};
// or
var newObject = Object.create( null );
// or
var newObject = new Object();
~~~
最后一個例子中"Object"構造器創建了一個針對特殊值的對象包裝,只不過這里沒有傳值給它,所以它將會返回一個空對象。
有四種方式可以將一個鍵值對賦給一個對象:
~~~
// ECMAScript 3 兼容形式
// 1\. “點號”法
// 設置屬性
newObject.someKey = "Hello World";
// 獲取屬性
var key = newObject.someKey;
// 2\. “方括號”法
// 設置屬性
newObject["someKey"] = "Hello World";
// 獲取屬性
var key = newObject["someKey"];
// ECMAScript 5 僅兼容性形式
// For more information see: http://kangax.github.com/es5-compat-table/
// 3\. Object.defineProperty方式
// 設置屬性
Object.defineProperty( newObject, "someKey", {
value: "for more control of the property's behavior",
writable: true,
enumerable: true,
configurable: true
});
// 如果上面的方式你感到難以閱讀,可以簡短的寫成下面這樣:
var defineProp = function ( obj, key, value ){
config.value = value;
Object.defineProperty( obj, key, config );
};
// 為了使用它,我們要創建一個“person”對象
var person = Object.create( null );
// 用屬性構造對象
defineProp( person, "car", "Delorean" );
defineProp( person, "dateOfBirth", "1981" );
defineProp( person, "hasBeard", false );
// 4\. Object.defineProperties方式
// 設置屬性
Object.defineProperties( newObject, {
"someKey": {
value: "Hello World",
writable: true
},
"anotherKey": {
value: "Foo bar",
writable: false
}
});
// 3和4中的讀取屬行可用1和2中的任意一種
~~~
在這本書的后面一點,這些方法會被用于繼承,如下:
~~~
// 使用:
// 創建一個繼承與Person的賽車司機
var driver = Object.create( person );
// 設置司機的屬性
defineProp(driver, "topSpeed", "100mph");
// 獲取繼承的屬性 (1981)
console.log( driver.dateOfBirth );
// 獲取我們設置的屬性 (100mph)
console.log( driver.topSpeed );
~~~
## 基礎構造器
正如我們先前所看到的,Javascript不支持類的概念,但它有一種與對象一起工作的構造器函數。使用new關鍵字來調用該函數,我們可以告訴Javascript把這個函數當做一個構造器來用,它可以用自己所定義的成員來初始化一個對象。
在這個構造器內部,關鍵字this引用到剛被創建的對象。回到對象創建,一個基本的構造函數看起來像這樣:
~~~
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
// 使用:
// 我們可以示例化一個Car
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
// 打開瀏覽器控制臺查看這些對象toString()方法的輸出值
// output of the toString() method being called on
// these objects
console.log( civic.toString() );
console.log( mondeo.toString() );
~~~
上面這是個簡單版本的構造器模式,但它還是有些問題。一個是難以繼承,另一個是每個Car構造函數創建的對象中,toString()之類的函數都被重新定義。這不是非常好,理想的情況是所有Car類型的對象都應該引用同一個函數。 這要謝謝 ECMAScript3和ECMAScript5-兼容版,對于構造對象他們提供了另外一些選擇,解決限制小菜一碟。
## 使用“原型”的構造器
在Javascript中函數有一個prototype的屬性。當我們調用Javascript的構造器創建一個對象時,構造函數prototype上的屬性對于所創建的對象來說都看見。照這樣,就可以創建多個訪問相同prototype的Car對象了。下面,我們來擴展一下原來的例子:
~~~
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
}
// 注意這里我們使用Note here that we are using Object.prototype.newMethod 而不是
// Object.prototype ,以避免我們重新定義原型對象
Car.prototype.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
// 使用:
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
console.log( civic.toString() );
console.log( mondeo.toString() );
~~~
通過上面代碼,單個toString()實例被所有的Car對象所共享了。
- 前言
- 簡介
- 什么是設計模式?
- 設計模式的結構
- 編寫設計模式
- 反模式
- 設計模式的分類
- 設計模式分類概覽表
- JavaScript 設計模式
- 構造器模式
- 模塊化模式
- 暴露模塊模式
- 單例模式
- 觀察者模式
- 中介者模式
- 原型模式
- 命令模式
- 外觀模式
- 工廠模式
- Mixin 模式
- 裝飾模式
- 亨元(Flyweight)模式
- JavaScript MV* 模式
- MVC 模式
- MVP 模式
- MVVM 模式
- 最新的模塊化 JavaScript 設計模式
- AMD
- CommonJS
- ES Harmony
- JQuery 中的設計模式
- 組合模式
- 適配器模式
- 外觀模式
- 觀察者模式
- 迭代器模式
- 惰性初始模式
- 代理模式
- 建造者模式
- jQuery 插件的設計模式
- JavaScript 命名空間模式
- 總結
- 參考