原型模式(Prototype pattern),用原型實例指向建立對象的類,使用於建立新的對象的類的共享原型的屬性與方法。html
對於原型模式,咱們能夠利用JavaScript特有的原型繼承特性去建立對象的方式,也就是建立的一個對象做爲另一個對象的prototype
屬性值。原型對象自己就是有效地利用了每一個構造器建立的對象,例如,若是一個構造函數的原型包含了一個name屬性(見後面的例子),那經過這個構造函數建立的對象都會有這個屬性。前端
在現有的文獻裏查看原型模式的定義,沒有針對JavaScript的,你可能發現不少講解的都是關於類的,可是現實狀況是基於原型繼承的JavaScript徹底避免了類(class)的概念。咱們只是簡單從現有的對象進行拷貝來建立對象。segmentfault
真正的原型繼承是做爲最新版的ECMAScript5標準提出的,使用Object.create
方法來建立這樣的對象,該方法建立指定的對象,其對象的prototype
有指定的對象(也就是該方法傳進的第一個參數對象),也能夠包含其餘可選的指定屬性。例如Object.create(prototype, optionalDescriptorObjects)
,下面的例子裏也能夠看到這個用法:設計模式
// 由於不是構造函數,因此不用大寫 var someCar = { drive: function () { }, name: '馬自達 3' }; // 使用Object.create建立一個新車x var anotherCar = Object.create(someCar); anotherCar.name = '豐田佳美';
Object.create
運行你直接從其它對象繼承過來,使用該方法的第二個參數,你能夠初始化額外的其它屬性。例如:緩存
var vehicle = { getModel: function () { console.log('車輛的模具是:' + this.model); } }; var car = Object.create(vehicle, { 'id': { value: MY_GLOBAL.nextId(), enumerable: true // 默認writable:false, configurable:false }, 'model': { value: '福特', enumerable: true } });
這裏,能夠在Object.create
的第二個參數裏使用對象字面量傳入要初始化的額外屬性,其語法與Object.defineProperties
或Object.defineProperty
方法相似。它容許您設定屬性的特性,例如enumerable
, writable
或 configurable
。微信
若是你但願本身去實現原型模式,而不直接使用Object.create
。你可使用像下面這樣的代碼爲上面的例子來實現:函數
var vehiclePrototype = { init: function (carModel) { this.model = carModel; }, getModel: function () { console.log('車輛模具是:' + this.model); } }; function vehicle(model) { function F() { }; F.prototype = vehiclePrototype; var f = new F(); f.init(model); return f; } var car = vehicle('福特Escort'); car.getModel();
原型模式在JavaScript裏的使用簡直是無處不在,其它不少模式有不少也是基於prototype的,這裏你們要注意的依然是淺拷貝和深拷貝的問題,省得出現引用問題。學習
原型模式適合在建立複雜對象時,對於那些需求一直在變化而致使對象結構不停地改變時,將那些比較穩定的屬性與方法共用而提取的繼承的實現。this
本文是系列文章,能夠相互參考印證,共同進步~spa
網上的帖子大多深淺不一,甚至有些先後矛盾,在下的文章都是學習過程當中的總結,若是發現錯誤,歡迎留言指出~
參考:
設計模式之原型模式
《Javascript 設計模式》 - 張榮銘
PS:歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~
另外能夠加入「前端下午茶交流羣」微信羣,長按識別下面二維碼便可加我好友,備註加羣,我拉你入羣~