# 構(gòu)造器模式
在面向?qū)ο缶幊讨校瑯?gòu)造器是一個當(dāng)新建對象的內(nèi)存被分配后,用來初始化該對象的一個特殊函數(shù)。在JavaScript中幾乎所有的東西都是對象,我們經(jīng)常會對對象的構(gòu)造器十分感興趣。
對象構(gòu)造器是被用來創(chuàng)建特殊類型的對象的,首先它要準(zhǔn)備使用的對象,其次在對象初次被創(chuàng)建時,通過接收參數(shù),構(gòu)造器要用來對成員的屬性和方法進行賦值。
## 對象創(chuàng)建
下面是我們創(chuàng)建對象的三種基本方式:
下面的每一種都會創(chuàng)建一個新的對象:
~~~
var newObject = {};
// or
var newObject = Object.create( null );
// or
var newObject = new Object();
~~~
最后一個例子中"Object"構(gòu)造器創(chuàng)建了一個針對特殊值的對象包裝,只不過這里沒有傳值給它,所以它將會返回一個空對象。
有四種方式可以將一個鍵值對賦給一個對象:
~~~
// ECMAScript 3 兼容形式
// 1\. “點號”法
// 設(shè)置屬性
newObject.someKey = "Hello World";
// 獲取屬性
var key = newObject.someKey;
// 2\. “方括號”法
// 設(shè)置屬性
newObject["someKey"] = "Hello World";
// 獲取屬性
var key = newObject["someKey"];
// ECMAScript 5 僅兼容性形式
// For more information see: http://kangax.github.com/es5-compat-table/
// 3\. Object.defineProperty方式
// 設(shè)置屬性
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 );
};
// 為了使用它,我們要創(chuàng)建一個“person”對象
var person = Object.create( null );
// 用屬性構(gòu)造對象
defineProp( person, "car", "Delorean" );
defineProp( person, "dateOfBirth", "1981" );
defineProp( person, "hasBeard", false );
// 4\. Object.defineProperties方式
// 設(shè)置屬性
Object.defineProperties( newObject, {
"someKey": {
value: "Hello World",
writable: true
},
"anotherKey": {
value: "Foo bar",
writable: false
}
});
// 3和4中的讀取屬行可用1和2中的任意一種
~~~
在這本書的后面一點,這些方法會被用于繼承,如下:
~~~
// 使用:
// 創(chuàng)建一個繼承與Person的賽車司機
var driver = Object.create( person );
// 設(shè)置司機的屬性
defineProp(driver, "topSpeed", "100mph");
// 獲取繼承的屬性 (1981)
console.log( driver.dateOfBirth );
// 獲取我們設(shè)置的屬性 (100mph)
console.log( driver.topSpeed );
~~~
## 基礎(chǔ)構(gòu)造器
正如我們先前所看到的,Javascript不支持類的概念,但它有一種與對象一起工作的構(gòu)造器函數(shù)。使用new關(guān)鍵字來調(diào)用該函數(shù),我們可以告訴Javascript把這個函數(shù)當(dāng)做一個構(gòu)造器來用,它可以用自己所定義的成員來初始化一個對象。
在這個構(gòu)造器內(nèi)部,關(guān)鍵字this引用到剛被創(chuàng)建的對象。回到對象創(chuàng)建,一個基本的構(gòu)造函數(shù)看起來像這樣:
~~~
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() );
~~~
上面這是個簡單版本的構(gòu)造器模式,但它還是有些問題。一個是難以繼承,另一個是每個Car構(gòu)造函數(shù)創(chuàng)建的對象中,toString()之類的函數(shù)都被重新定義。這不是非常好,理想的情況是所有Car類型的對象都應(yīng)該引用同一個函數(shù)。 這要謝謝 ECMAScript3和ECMAScript5-兼容版,對于構(gòu)造對象他們提供了另外一些選擇,解決限制小菜一碟。
## 使用“原型”的構(gòu)造器
在Javascript中函數(shù)有一個prototype的屬性。當(dāng)我們調(diào)用Javascript的構(gòu)造器創(chuàng)建一個對象時,構(gòu)造函數(shù)prototype上的屬性對于所創(chuàng)建的對象來說都看見。照這樣,就可以創(chuàng)建多個訪問相同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對象所共享了。
- 前言
- 簡介
- 什么是設(shè)計模式?
- 設(shè)計模式的結(jié)構(gòu)
- 編寫設(shè)計模式
- 反模式
- 設(shè)計模式的分類
- 設(shè)計模式分類概覽表
- JavaScript 設(shè)計模式
- 構(gòu)造器模式
- 模塊化模式
- 暴露模塊模式
- 單例模式
- 觀察者模式
- 中介者模式
- 原型模式
- 命令模式
- 外觀模式
- 工廠模式
- Mixin 模式
- 裝飾模式
- 亨元(Flyweight)模式
- JavaScript MV* 模式
- MVC 模式
- MVP 模式
- MVVM 模式
- 最新的模塊化 JavaScript 設(shè)計模式
- AMD
- CommonJS
- ES Harmony
- JQuery 中的設(shè)計模式
- 組合模式
- 適配器模式
- 外觀模式
- 觀察者模式
- 迭代器模式
- 惰性初始模式
- 代理模式
- 建造者模式
- jQuery 插件的設(shè)計模式
- JavaScript 命名空間模式
- 總結(jié)
- 參考
