天天看點

constructor設計模式

在經典的面向對象程式設計語言中,constructor是一個特殊的方法,被用來初始化一個建立的對象,一旦該對象被配置設定記憶體話。

在JavaScript中幾乎所有的東西都是一個對象,然而常常引起我們興趣的是對象的constructor。

對象的構造函數用于建立特定類型的對象(既要準備使用對象,也要接收參數),構造函數在建立對象時可以用來設定成員屬性和方法的值。

建立對象

在JavaScript中建立對象的三種通用方法如下:

// 每種方法将建立一個空對象

var newObject = {}

// or

var newObject = Object.create( Object.prototype )

// or

var newObject = new Object();
           

最後一個方法實作對象的建立可以傳入指定的值,如果沒有傳遞,将建立一個空對象,然後傳回它。

傳入String,傳回String,類似于new String();
傳入Number,傳回Number,類似于new Number();
傳入Object,傳回Object,相當于沒傳
           

為對象指定鍵和值有如下四種方法:

相容ES3的方法

// 1. `.`(Dot) 文法
// 設定屬性
newObject.someKey = 'Hello world';
// 擷取屬性
var value = newObject.somekey;


// 2. '[]'方括号文法
// 設定屬性
newObject["someKey"] = "Hello World";
// 擷取屬性
var value = newObject["someKey"];
           

相容ES5的方法(要了解更多的資訊,請轉

http://kangax.github.com/es5-compat-table/

// 3. Object.defineProperty
// 設定屬性
Object.defineProperty(newObject, "someKey", {
    value: "Hello World",
    writable: true,
    enumerable: true,
    configurable: true
})
// 擷取屬性的方法,用1,2中方法即可

// 詳細了解Object.defineProperty的使用可參考[https://segmentfault.com/a/1190000007434923](https://segmentfault.com/a/1190000007434923)

// 4. Object.defineProperties
// 設定屬性

Object.defineProperties(newObject, {
    "someKey": {
        value: "Hello World",
        writable: true
    },
    "anotherKey": {
        value: "Ha ha",
        writable: true
    }
})

// 擷取屬性的方法,用1,2中方法即可
           

對象的繼承

前面我們說到幾種的對象的建立方式,在三種對象的建立中,第一種方式最簡單,效率更高,其他兩種内部都用了對象的繼承,如果沒有傳入任何參數,實作和第一種相似。下面試第二三種建立對象的執行個體:

// 第二種
var obj = {};
obj.a=1;
obj.a -> 1
var obj2 = Object.create(obj)
obj2.a -> 1

// 第三種
var obj = {};
obj.a = 1;
obj.a -> 1
var obj2  = new Object(obj);
obj2.a -> 1
           

是以隻是要建立一個空對象,第一種方法更好,要實作對象的繼承用第二三種方法,第二三種方法的差別在于前者是ES3,後者是ES5。

// Object.create 的内部實作如下:
Object.create = function(o) {
    function F(){}
    F.prototype=o;
    return new F();
}
           

constructor 基礎

衆所周知,JavaScript一門不支援

class

這個概念,但是它支援對象的構造函數,通過關鍵字

new

我們想要一個構造函數建立一個對象和它用函數定義的成員。

在constructor的内部,

this

關鍵字是被建立的新對象的引用。重溫對象的建立過程,一個基礎的 constructor 如下所示:

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 );
 
// 結果輸出
console.log( civic.toString() ); -> "Honda Civic has done 20000 miles"
console.log( mondeo.toString() ); -> "Ford Mondeo has done 5000 miles"·
           

如果現在就把它定義為一個設計模式相信,很多人對不會用它,因為它存在着一些問題。其中一個就是繼承性,另一個是每建立一個對象執行個體,

toString()

方法都要被重新定義,理想的實作方式是要實作

toString()

在不同的執行個體類型之間共享。

constructor 和 prototype

在JavaScript中,

Function

像其他對象一樣,有一個

prototype

。當我們用contructor建立一個對象,所有constructor的 prototype上的屬性都将被新對象繼承。是以上面的例子我們可以修改如下:

function Car( model, year, miles ) {
    this.model = model;
    this.year = year;
    this.miles = miles;
}

Car.prototype.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 );
 
// 結果輸出
console.log( civic.toString() ); -> "Honda Civic has done 20000 miles"
console.log( mondeo.toString() ); -> "Ford Mondeo has done 5000 miles"·
           

這樣,

toString()

将實作在不同的對象執行個體間的共享。

其它設計模式相關文章請轉

‘大處着眼,小處着手’——設計模式系列

繼續閱讀