在面向?qū)ο缶幊讨?,?gòu)造器是一個當新建對象的內(nèi)存被分配后,用來初始化該對象的一個特殊函數(shù)。在JavaScript中幾乎所有的東西都是對象,我們經(jīng)常會對對象的構(gòu)造器十分感興趣。
對象構(gòu)造器是被用來創(chuàng)建特殊類型的對象的,首先它要準備使用的對象,其次在對象初次被創(chuàng)建時,通過接收參數(shù),構(gòu)造器要用來對成員的屬性和方法進行賦值。
下面是我們創(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 );
正如我們先前所看到的,Javascript不支持類的概念,但它有一種與對象一起工作的構(gòu)造器函數(shù)。使用new關(guān)鍵字來調(diào)用該函數(shù),我們可以告訴Javascript把這個函數(shù)當做一個構(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)造對象他們提供了另外一些選擇,解決限制小菜一碟。
在Javascript中函數(shù)有一個prototype的屬性。當我們調(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對象所共享了。
更多建議: