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=PersonPerson.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); //falseconsole.info(p1.hello == p2.hello); //falseconsole.info(p1.say === p2.say); //truep1.say("qq");p2.say("qq");console.info(p1.version === p2.version); //trueconsole.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.0Person.prototype.version = 2.0; //修改原型共享属性console.info(pB.version); //2.0console.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 RunmoduleB.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 RunparentModule.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原型模式内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net! 下载地址: Vue实现调用PC端摄像头实时拍照 javascript实现输入框内容提示及隐藏功能 |