JS設計模式 - 原型模式與建構函式模式
1. 原型模式 原型模式稱為基於現有對象的模板通過複製來建立對象的模式。
我們可以將原型模式視為基於原型繼承,在原型繼承中我們建立對象作為其他對象的原型。原型對象本身被有效地用作建構函式建立的每個對象的藍圖。
ECMAScript 5標準中定義的真正的原型繼承,需要使用Object.create。為了提醒自己,Object.create建立一個具有指定原型的對象,並且還可以包含指定的屬性(例如Object.create( prototype, optionalDescriptorObjects ))。
var myCar = { name: "Ford Escort", drive: function () { console.log( "Weeee. I'm driving!" ); }, panic: function () { console.log( "Wait. How do you stop this thing?" ); } }; // Use Object.create to instantiate a new carvar yourCar = Object.create( myCar ); // Now we can see that one is a prototype of the otherconsole.log( yourCar.name );
Object.create也使我們能夠輕鬆實現進階概念,如差異繼承,其中對象能夠直接從其他對象繼承。我們之前看到,Object.create允許我們使用第二個提供的參數初始化對象屬性。例如:
var vehicle = { getModel: function () { console.log( "The model of this vehicle is.." + this.model ); }}; var car = Object.create(vehicle, { "id": { value: MY_GLOBAL.nextId(), // writable:false, configurable:false by default enumerable: true }, "model": { value: "Ford", enumerable: true } });
如果我們希望不直接使用原型模式Object.create,我們可以按照上面的例子類比模式如下:
var vehiclePrototype = { init: function ( carModel ) { this.model = carModel; }, getModel: function () { console.log( "The model of this vehicle is.." + this.model); }}; function vehicle( model ) { function F() {}; F.prototype = vehiclePrototype; var f = new F(); f.init( model ); return f; } var car = vehicle( "Ford Escort" );car.getModel();
Prototype模式的最後一種替代實現可能如下:
var beget = (function () { function F() {} return function ( proto ) { F.prototype = proto; return new F(); };})();
2. 原型模式與建構函式模式
建構函式的相關內容請查看 JS原型模式與建構函式模式
上圖中建構函式模式的兩種屬性,執行個體屬性與共有屬性,因為建構函式模式如果沒有使用prototype方式的話,我們只能叫做這兩個名字,所以為了相容不適用prototype的方式,這裡暫且叫做這兩個和名字。至於原型模式的話就是自有屬性與從原型鏈上繼承而來的屬性。
首先二者的建立對象的方式不同,原型模式必須擁有prototype的存在,而建構函式方式不必依賴prototype。
第二的是談一下自己對於二者之間的一些理解吧。就好像在日常開發中這個team中有許多的成員,內部也會有小組。所有的成員相對於team來講的話,那就是建構函式模式,這裡team並不是指某一個個體,而是相當於一個function,我們所有的成員因為這個team工作在一起。在日常開發中,team對於我們的限制其實不大,只有當我們面向整個凍死的時候,才會提到我們的共有屬性,某一個team。大部分的時間我們還是坐著自己的事情(執行個體屬性)。
然後我上面有一個leader,我們兩個一組,現在這個leader,我就是相當於原型模式,現在這個原型對象就是leader,我在這個組裡工作就一定會有一些leader定義的工作方式(繼承屬性),當然也有一些自己處理問題的方式(自有屬性)
這個例子可能不太恰當,更多的理解我認為二者的側重點不同,儘管看起來沒有什麼區別。建構函式模式側重於處理多個對象,只是想要說明這些對象一些共同點,但是不會對於個體有很多的限制。原型模式的側重點應該是處理較少的對象,需要原型對象與執行個體對象的緊密聯絡,會對執行個體對象有著較多的限制。
note: 不管對於建構函式模式的共有屬性,還是原型對象的繼承屬性,執行個體對象都是可以重寫的。