原型模式


原型模式用于在创建对象时,通过共享某个对象原型的属性和方法,从而达到提高性能、降低内存占用、代码复用的效果。
  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();

该函数创建实例时原型图如下:

  1. 示例二
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);

该函数创建实例时原型图如下:

  1. 示例三
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");
  1. 总结

    js 在创建对象比较消耗内存、耗时长,可以通过减少内部属性创建的方式降低内存占用。

    而原型模式就是使用 javascript 语言的原型特性进行相同属性的共享,从而达到降低内存占用、提高对象创建效率。

观察者模式


观察者模式用于模块、组件之间通讯,通过提供统一的模式进行事件订阅、事件发布。从而达到模块、组件之间解耦,提高代码的可维护性。

模块之间、组件之间通讯方式

模块之间、组件之间采用直接引用通讯方式

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设计模式之原型模式、发布订阅模式的更多相关文章

  1. 理解JavaScript设计模式与开发应用中发布-订阅模式的最终版代码

    最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线 ...

  2. js 设计模式:观察者和发布订阅模式

    总是把这两个当作同一个模式,但其实是不太一样的,现在重温一下. 观察者模式 观察者直接订阅目标,当目标触发事件时,通知观察者进行更新 简单实现 class Observer { constructor ...

  3. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_8.RabbitMQ研究-工作模式-发布订阅模式-生产者

    Publish/subscribe:发布订阅模式 发布订阅模式: 1.每个消费者监听自己的队列. 2.生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将 ...

  4. javascript设计模式学习之八_发布订阅(观察者)模式

    一.发布订阅模式定义 jQuery中的callbacks,defered,promise本质上就是发布订阅模式的实现.ES6的promise内部实现未开源,不了解具体机制 发布订阅模式又叫做观察者模式 ...

  5. JS设计模式(5)发布订阅模式

    什么是发布订阅模式(观察者模式)? 定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且 ...

  6. 4.js模式-发布-订阅模式

    1. 发布-订阅模式 var observe = (function(){ var events = {}, listen, trigger, remmove; listen = function(k ...

  7. RabbitMQ六种队列模式-发布订阅模式

    前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅 [本文]RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...

  8. 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_9.RabbitMQ研究-工作模式-发布订阅模式-消费者

    消费者需要写两个消费者 定义邮件的类 复制以前的代码到邮件类里面进行修改 最上面 声明队列的名称和交换机的名称 监听修改为email 的队列的名称 手机短信接收端 复制一份email的接收端的代码 改 ...

  9. java设计模式之-观察者模式(发布-订阅模式)

    1.观察者模式定义  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象. 这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己. 2.观察者模式结构 ...

  10. java 观察这模式(发布订阅模式)

    观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息. 抽象 ...

随机推荐

  1. const 修饰

    int * const grape_jelly; 指针是只读的. const int * grape; int const * grape; 指针所指向的对象是只读的. 对象和指针有可能都是只读的: ...

  2. 设计模式<一>

    设计原则1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起. 2.针对接口编程,而不是针对实现编程. 3.多用组合,少用继承. 一:策略模式,定义了算法族,分别封装起来 ...

  3. 你知道 ES6~ES12等叫法是怎么来的吗?

    你知道 ES6~ES12等叫法是怎么来的吗? 前言 作为一名前端开发,学习 JavaScript 自是天经地义的事,但是,JavaScript 的发展历史是怎样的,恐怕有相当一部分人都不太了解. 我们 ...

  4. IDEA中的Git操作,看这一篇就够了!

    大家在使用Git时,都会选择一种Git客户端,在IDEA中内置了这种客户端,可以让你不需要使用Git命令就可以方便地进行操作,本文将讲述IDEA中的一些常用Git操作. 环境准备 使用前需要安装一个远 ...

  5. rasa 如何写一个故事

    设计故事 在设计故事时,需要考虑两组对话交互:快乐路径和不快乐路径.快乐路径描述用户何时按照您的预期遵循对话流程,并在出现提示时始终提供必要的信息.然而,用户经常会因为问题.闲聊或其他问题而偏离愉快的 ...

  6. 一次PHP大马提权

    记一次PHP提权 发现 PHP大马:指木马病毒:PHP大马,就是PHP写的提取站点权限的程序:因为带有提权或者修改站点功能,所以称为叫木马. 自从师哥那里听说过之后,一直感叹于PHP大马的神奇...但 ...

  7. 【CSS】按钮

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. string类型数据的操作指令

    1. 2. 3. 4. 5. 6. 7. 8. 9. 从右到左是索引从-1开始 10. 11. 12. 13. 14. 15.

  9. Linux内核编译配置脚本

    环境 宿主机平台:Ubuntu 16.04.6 目标机:iMX6ULL Linux内核编译配置脚本 在linux开发过程中熟练使用脚本可以大大简化命令行操作,同时对于需要经常重复操作的指令也是一种备忘 ...

  10. 阶段总结-Java基础-超进阶

    Gitee项目地址:https://gitee.com/zc10010/java_interview_guide/tree/master/知识点话术 项目叫话术,但是我觉得作为知识点学习是挺不错的. ...