3.Contructor(構造器)模式—精讀《JavaScript 設計模式》Addy Osmani著

Wumw發表於2018-11-12

同系列友情連結:


1.設計模式之初體驗—精讀《JavaScript 設計模式》Addy Osmani著
2.設計模式的分類—精讀《JavaScript 設計模式》Addy Osmani著

Construct(構造器)模式


在經典的物件導向程式語言中,Construtor是一種在記憶體已分配給該物件的情況下,用於初始化新建立物件的特殊方法。

在 JavaScript 中,幾乎所有東西都是都是物件,可能你會經常找不到物件,?,你承認不??

來看一下什麼是 Object構造器 :

用於建立特定型別的物件——準備好物件以備使用,同時接受構造器可以使用的引數,以在第一次建立物件時,設定成員屬性和方法值。

下圖為:Constructor(構造器)模式

Object構造器

物件的建立

在 JavaScript 中,建立物件時有發生,常見的建立方式有兩種:

  1. 直接空物件賦值;
  2. 使用 new關鍵字
// 1. 直接空物件賦值
var newObject = {};

// 2. 使用 new 關鍵字建立,newObject構造器的簡潔記法
var newObject = new Object();
複製程式碼

在 Object構造器為特定的值建立物件封裝,或者沒有傳遞值時,它將建立 一個空物件並返回這個空物件;

物件的賦值

四種方法可以將鍵值賦值給一個物件:

  1. ECMAScript 3 相容方式;
    1. “點”語法;
    2. 中括號語法
  2. 只適用於ECMAScript 5 方式;
    1. Object.defineProperty;
    2. 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(模組)模式做詳細的介紹。這一模式更精彩,因為很快你就會知道為什麼別人都那麼寫了,以及模組化的相關概念等等等

( ^_^ )/~~拜拜

相關文章