目录
- 1、原型模式
- 示例一
- 示例二
- 示例三
- 2、观察者模式
1、原型模式
原型模式用于在创建对象时,通过共享某个对象原型的属性和方法,从而达到提高性能、降低内存占用、代码复用的效果。
示例一
function Person(name) { this.name = name; this.config = { a: "1", b: "2", }; this.hello = function () { console.info("hello"); }; }
假如需要通过以上代码创建 100 个实例,那么将需要创建 100 个 config
、100 个 hello
,而这两个东西在每个实例里面是完全一样的。
因此我们可以通过提取公共代码的方式进行油优化。
const config = { a: "1", b: "2", }; const hello = function () { console.info("hello"); }; function Person(name) { this.name = name; this.config = config; this.hello = hello }
这样的方式使得无论创建多少个Person对象都只需要创建一个config
、一个hello
。 但是仍然污染全局变量、config
被误修改、Person
和其他代码耦合大、不易于代码扩展维护等问题。
因此可以通过原型的方式进行优化。
function Person() {} var p = new Person();
该函数创建实例时原型图如下:
示例二
function Person(name) { this.name = name; this.config = { a: "1", b: "2", }; this.hello = function () { console.info("hello"); }; } //此方式会重写prototype,造成constructor丢失,变为Object()。 //可以使用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);
该函数创建实例时原型图如下:
示例三
function Person(name) { this.name = name; this.config = { a: "1", b: "2", }; this.hello = function () { console.info("hello"); }; } //此方式会重写prototype,造成constructor丢失,变为Object() 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 内部属性比较 console.info(pA.hello == pB.hello); //false 内部属性比较 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");
总结:
js 在创建对象比较消耗内存、耗时长,可以通过减少内部属性创建的方式降低内存占用。
而原型模式就是使用
javascript
语言的原型特性进行相同属性的共享,从而达到降低内存占用、提高对象创建效率。
2、观察者模式
观察者模式用于模块、组件之间通讯,通过提供统一的模式进行事件订阅、事件发布。从而达到模块、组件之间解耦,提高代码的可维护性。
模块之间、组件之间通讯方式
模块之间、组件之间采用直接引用通讯方式
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
事件模块实现通讯
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中注册事件 const methodA = (data) => { console.info("模块A接受到food消息:"); console.info(data); }; emitter.on("food", methodA); //模块B中注册事件 const methodB = (data) => { console.info("模块B接受到food消息:"); console.info(data); }; emitter.on("food", methodB); //模块C中触发事件 emitter.fire("food", "饭来了"); //模块B中移除事件 emitter.remove("food", methodB); //模块C中再次触发事件 emitter.fire("food", "饭又来了");
执行结果如下:
模块 A 接受到 food 消息:
饭来了
模块 B 接受到 food 消息:
饭来了
模块 A 接受到 food 消息:
饭又来了
总结:
js 组件模块的通讯方式一般分为3种(直接通讯、通过父组件通讯、通过事件模块通讯)。观察者模式用于模块、组件之间通讯,通过提供统一的模式进行事件订阅、事件发布,从而达到模块、组件之间解耦,提高代码的可维护性
到此这篇关于Javascript设计模式之原型模式详细的文章就介绍到这了,更多相关Javascript原型模式内容请搜索NICE源码以前的文章或继续浏览下面的相关文章希望大家以后多多支持NICE源码!