Javascript設(shè)計(jì)模式之原型模式詳細(xì)
1、原型模式
原型模式用于在創(chuàng)建對(duì)象時(shí),通過共享某個(gè)對(duì)象原型的屬性和方法,從而達(dá)到提高性能、降低內(nèi)存占用、代碼復(fù)用的效果。
示例一
function Person(name) { this.name = name; this.config = { a: "1", b: "2", }; this.hello = function () { console.info("hello"); }; }
假如需要通過以上代碼創(chuàng)建 100 個(gè)實(shí)例,那么將需要?jiǎng)?chuàng)建 100 個(gè) config
、100 個(gè) hello
,而這兩個(gè)東西在每個(gè)實(shí)例里面是完全一樣的。
因此我們可以通過提取公共代碼的方式進(jìn)行油優(yōu)化。
const config = { a: "1", b: "2", }; const hello = function () { console.info("hello"); }; function Person(name) { this.name = name; this.config = config; this.hello = hello }
這樣的方式使得無(wú)論創(chuàng)建多少個(gè)Person對(duì)象都只需要?jiǎng)?chuàng)建一個(gè)config
、一個(gè)hello
。 但是仍然污染全局變量、config
被誤修改、Person
和其他代碼耦合大、不易于代碼擴(kuò)展維護(hù)等問題。
因此可以通過原型的方式進(jìn)行優(yōu)化。
function Person() {} var p = new Person();
該函數(shù)創(chuàng)建實(shí)例時(shí)原型圖如下:
示例二
function Person(name) { this.name = name; this.config = { a: "1", b: "2", }; this.hello = function () { console.info("hello"); }; } //此方式會(huì)重寫prototype,造成constructor丟失,變?yōu)镺bject()。 //可以使用Person.prototype.xx=yy的方式寫,或者重新指定Person.prototype.constructor=Person Person.prototype = { version: 1.0, say: function (arg) { console.info(`${this.name} say ${arg}`); }, constructor: Person, }; var p1 = new Person("p1"); var p2 = new Person("p2"); console.info(p1.config == p2.config); //false console.info(p1.hello == p2.hello); //false console.info(p1.say === p2.say); //true p1.say("qq"); p2.say("qq"); console.info(p1.version === p2.version); //true console.info(p1.version);
該函數(shù)創(chuàng)建實(shí)例時(shí)原型圖如下:
示例三
function Person(name) { this.name = name; this.config = { a: "1", b: "2", }; this.hello = function () { console.info("hello"); }; } //此方式會(huì)重寫prototype,造成constructor丟失,變?yōu)镺bject() Person.prototype = { version: 1.0, say: function (arg) { console.info(`${this.name} say ${arg}`); }, }; function PersonA(name) { Person.call(this, name); } PersonA.prototype = Person.prototype; function PersonB(name) { Person.call(this, name); } PersonB.prototype = Person.prototype; var pA = new PersonA("pa"); var pB = new PersonB("pb"); console.info(pA.config == pB.config); //false 內(nèi)部屬性比較 console.info(pA.hello == pB.hello); //false 內(nèi)部屬性比較 console.info(pA.say === pB.say); //true 原型方法共享 pA.say("qq"); pB.say("qq"); console.info(pA.version === pB.version); //true 原型屬性共享 console.info(pA.version); //1.0 Person.prototype.version = 2.0; //修改原型共享屬性 console.info(pB.version); //2.0 console.info(new Person().version); //2.0 //修改原型共享方法 PersonB.prototype.say = function (arg) { console.info(`v2--- ${this.name} say ${arg}`); }; pB.say("qq"); new Person("Person").say("ww");
總結(jié):
js 在創(chuàng)建對(duì)象比較消耗內(nèi)存、耗時(shí)長(zhǎng),可以通過減少內(nèi)部屬性創(chuàng)建的方式降低內(nèi)存占用。
而原型模式就是使用
javascript
語(yǔ)言的原型特性進(jìn)行相同屬性的共享,從而達(dá)到降低內(nèi)存占用、提高對(duì)象創(chuàng)建效率。
2、觀察者模式
觀察者模式用于模塊、組件之間通訊,通過提供統(tǒng)一的模式進(jìn)行事件訂閱、事件發(fā)布。從而達(dá)到模塊、組件之間解耦,提高代碼的可維護(hù)性。
模塊之間、組件之間通訊方式
模塊之間、組件之間采用直接引用通訊方式
const moduleA = { say: function (msg) { console.info("A say " + msg); }, letBrun: function () { //直接引用了moduleB moduleB.run(); }, }; const moduleB = { run: function () { console.info("B run "); }, letAsay: function () { //直接引用了moduleA moduleA.say("hello"); }, }; moduleA.letBrun(); //B Run moduleB.letAsay(); //A say hello
模塊之間、組件之間采用父組件通訊方式
const moduleA = { say: function (msg) { console.info("A say " + msg); }, }; const moduleB = { run: function () { console.info("B run "); }, }; const parentModule = { moduleA, moduleB, letBrun: function () { this.moduleB.run(); }, letAsay: function () { this.moduleA.say("hello"); }, }; parentModule.letBrun(); //B Run parentModule.letAsay(); //A say hello
事件模塊實(shí)現(xiàn)通訊
function Emitter() { this.events = {}; this.res_oldAction = {} this.res_action_events = {} } //訂閱資源 Emitter.prototype.subscribe = function (res, action, fn) { if(!this.res_oldAction[res.name]){ this.res_oldAction[res.name] = res[action] res[action] = (data) => { this.res_oldAction[res.name](data) const fns = this.res_action_events[res.name].action; for (let i = 0; i < fns.length; i++) { fns[i](data); } } } if(!this.res_action_events[res.name]){ this.res_action_events[res.name] = {} } if(!this.res_action_events[res.name][action]){ this.res_action_events[res.name][action] = [] } this.res_action_events[res.name].action.push(fn) } //取消訂閱資源 Emitter.prototype.unsubscribe = function (res, action, fn) { const fns = this.res_action_events[res.name].action; for (let i = 0; i < fns.length; i++) { if (fns[i] === fn) { fns.splice(i, 1); i--; } } } Emitter.prototype.on = function (name, fn) { if (!this.events[name]) { this.events[name] = []; } this.events[name].push(fn); }; Emitter.prototype.remove = function (name, fn) { if (!this.events[name]) { return; } const fns = this.events[name]; for (let i = 0; i < fns.length; i++) { if (fns[i] === fn) { fns.splice(i, 1); i--; } } }; Emitter.prototype.fire = function (name, data) { if (!this.events[name]) { return; } const fns = this.events[name]; for (let i = 0; i < fns.length; i++) { fns[i](data); } }; const emitter = new Emitter(); //模塊A中注冊(cè)事件 const methodA = (data) => { console.info("模塊A接受到food消息:"); console.info(data); }; emitter.on("food", methodA); //模塊B中注冊(cè)事件 const methodB = (data) => { console.info("模塊B接受到food消息:"); console.info(data); }; emitter.on("food", methodB); //模塊C中觸發(fā)事件 emitter.fire("food", "飯來(lái)了"); //模塊B中移除事件 emitter.remove("food", methodB); //模塊C中再次觸發(fā)事件 emitter.fire("food", "飯又來(lái)了");
執(zhí)行結(jié)果如下:
模塊 A 接受到 food 消息:
飯來(lái)了
模塊 B 接受到 food 消息:
飯來(lái)了
模塊 A 接受到 food 消息:
飯又來(lái)了
總結(jié):
js 組件模塊的通訊方式一般分為3種(直接通訊、通過父組件通訊、通過事件模塊通訊)。觀察者模式用于模塊、組件之間通訊,通過提供統(tǒng)一的模式進(jìn)行事件訂閱、事件發(fā)布,從而達(dá)到模塊、組件之間解耦,提高代碼的可維護(hù)性
到此這篇關(guān)于Javascript設(shè)計(jì)模式之原型模式詳細(xì)的文章就介紹到這了,更多相關(guān)Javascript原型模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中使用toLocaleString數(shù)字格式化處理詳解
這篇文章主要為大家介紹了JavaScript中使用toLocaleString數(shù)字格式化處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08TypeScript?學(xué)習(xí)筆記之?typeScript類定義,類的繼承,類成員修飾符
這篇文章主要介紹了TypeScript?學(xué)習(xí)筆記之?typeScript類定義,類的繼承,類成員修飾符,typeScript?支持面向?qū)ο蟮乃刑匦?,比如類、接口?下文詳細(xì)內(nèi)容,需要的小伙伴可以參考一下2022-02-02JavaScript?執(zhí)行上下文的視角詳解this使用
這篇文章主要為以JavaScript?執(zhí)行上下文的視角為大家講清楚?this使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02微信小程序 簡(jiǎn)單實(shí)例(閱讀器)的實(shí)例開發(fā)
這篇文章主要介紹了微信小程序 簡(jiǎn)單實(shí)例(閱讀器)的實(shí)例開發(fā)的相關(guān)資料,需要的朋友可以參考下2016-09-09微信小程序 網(wǎng)絡(luò)API 上傳、下載詳解
這篇文章主要介紹了微信小程序 網(wǎng)絡(luò)API 上傳、下載詳解的相關(guān)資料,需要的朋友可以參考下2016-11-11Javascript繼承(上)——對(duì)象構(gòu)建介紹
Javascript中除了基本數(shù)據(jù)(Undefined、Null、Boolean、Number、String),其他都是對(duì)象(Object)2012-11-11微信小程序 使用picker封裝省市區(qū)三級(jí)聯(lián)動(dòng)實(shí)例代碼
這篇文章主要介紹了微信小程序 使用picker封裝省市區(qū)三級(jí)聯(lián)動(dòng)實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10