同系列友情鏈接:
1.設計模式之初體驗—精讀《JavaScript 設計模式》Addy Osmani著
2.設計模式的分類—精讀《JavaScript 設計模式》Addy Osmani著
Construct(構造器)模式
在經典的面向對象編程語言中,Construtor是一種在內存已分配給該對象的情況下,用于初始化新創建對象的特殊方法。
在 JavaScript 中,幾乎所有東西都是都是對象,可能你會經常找不到對象,?,你承認不??
來看一下什么是 Object構造器 :
用于創建特定類型的對象——準備好對象以備使用,同時接受構造器可以使用的參數,以在第一次創建對象時,設置成員屬性和方法值。
下圖為:Constructor(構造器)模式
對象的創建
在 JavaScript 中,創建對象時有發生,常見的創建方式有兩種:
- 直接空對象賦值;
- 使用 new關鍵字
// 1. 直接空對象賦值
var newObject = {};// 2. 使用 new 關鍵字創建,newObject構造器的簡潔記法
var newObject = new Object();
復制代碼
在 Object構造器為特定的值創建對象封裝,或者沒有傳遞值時,它將創建 一個空對象并返回這個空對象;
對象的賦值
四種方法可以將鍵值賦值給一個對象:
- ECMAScript 3 兼容方式;
- “點”語法;
- 中括號語法
- 只適用于ECMAScript 5 方式;
- Object.defineProperty;
- Object.defineProperties
// 1.點語法
// 設置屬性
newObject.someKey = "Hello World!";
// 獲取屬性值
var key = newObject.someKey;// 2.中括號語法
// 設置屬性
newObject["somekey"] = "Hello world!";
// 獲取屬性值
var key = newObject["somekey"];// 3.Object.defineProperty
// 設置屬性
Object.defineProperty(newObject,"somekey",{value:"Hello World!",// 該屬性對應的值,默認為undefinedwritable:true,// 能否修改屬性的值,如果直接使用字面量定義對象,默認值為trueenumerable:true,// 表示該屬性是否可枚舉,即是否通過for-in循環或Object.keys()返回屬性,如果直接使用字面量定義對象,默認值為trueconfigurable:true// 表示能否通過delete刪除此屬性,能否修改屬性的特性,或能否修改把屬性修改為訪問器屬性,如果直接使用字面量定義對象,默認值為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,"dateOfBrith","1989");
defineProp(person,"hasBeard",false);
// 獲取屬性值同1,2
var key_car = person["car"];
var key_dateOfBrith = person["dateOfBrith"];
var key_hasBeard = person["hasBeard"];// 4.Object.defineProperties
// 設置屬性
Object.defineProperties(newObject,{"someKey":{value:"Hello World!",writable:true},"anotherKey":{value:"Foo Bar",writable:false}
});
// 獲取屬性值同1,2
var key_someKey = person["someKey"];
var key_anotherKey = person["anotherKey"];復制代碼
上面定義的這些方法甚至可以用于繼承如下所示:
// 用法
// 創建賽車司機 driver 對象,繼承于 person 對象
var driver = Object.create(person);
// 為 driver 設置一些屬性
defineProp(deriver,"topSpeed","100mph");
// 獲取繼承屬性
console.log(driver.dateOfBrith);
// 獲取我們設置的100mph屬性
console.log(driver.topSpeed);復制代碼
基本Constructor(構造器)
大家都知道 JavaScript 不支持類的概念,但是它卻支持與對象一起使用的 特殊的 Constructor 函數。通過在構造器前面加 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";}
}
// 用法
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 構造器創建的新對象而重新定義的。 這不是最理想的,因為這種函數應該在所有的 Car 實例之間共享。
其實這個問題很好解決,因為有很多ES3和 ES5兼容替代方法能夠用于創建對象。
帶原型的Constructor(構造器)
JavaScript中有一個名為 prototype 的屬性。調用 JavaScript 構造器創建一個對象后,新的對象就具有構造器原型的所有屬性。通過這種方式,可以創建多個 Car 對象,并訪問相同的原型。所以我們可以擴展原始示例,如下所示:
function Car(model,year,miles){this.model = model;this.year = year;this.miles = miles;
}
// 前方警告:小伙伴是否還記得反模式一條:避免重新定義 prototype對象
// 所以下面我們是使用 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 對象之間共享了
復制代碼
小結
今天的構造器模式,是不是很nice?
但是,你掌握了多少?
你可以動動小手指示例代碼都敲一遍,相信你可以更進一步了解,掌握 Constructor(構造器)模式。
下一篇將對Module(模塊)模式做詳細的介紹。這一模式更精彩,因為很快你就會知道為什么別人都那么寫了,以及模塊化的相關概念等等等
( ^_^ )/~~拜拜