同系列友情連結:
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!",// 該屬性對應的值,預設為undefined
writable:true,// 能否修改屬性的值,如果直接使用字面量定義物件,預設值為true
enumerable:true,// 表示該屬性是否可列舉,即是否通過for-in迴圈或Object.keys()返回屬性,如果直接使用字面量定義物件,預設值為true
configurable: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(模組)模式做詳細的介紹。這一模式更精彩,因為很快你就會知道為什麼別人都那麼寫了,以及模組化的相關概念等等等
( ^_^ )/~~拜拜