Javascript设计模式之原型模式详细

目录

  • 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();

    该函数创建实例时原型图如下:
    Javascript设计模式之原型模式详细
    文章图片


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

    该函数创建实例时原型图如下:
    Javascript设计模式之原型模式详细
    文章图片


    示例三
    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 语言的原型特性进行相同属性的共享,从而达到降低内存占用、提高对象创建效率。
    【Javascript设计模式之原型模式详细】
    2、观察者模式
    观察者模式用于模块、组件之间通讯,通过提供统一的模式进行事件订阅、事件发布。从而达到模块、组件之间解耦,提高代码的可维护性。
    模块之间、组件之间通讯方式
    Javascript设计模式之原型模式详细
    文章图片

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

    const moduleA = {say: function (msg) {console.info("A say " + msg); },letBrun: function () {//直接引用了moduleBmoduleB.run(); },}; const moduleB = {run: function () {console.info("B run "); },letAsay: function () {//直接引用了moduleAmoduleA.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原型模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

      推荐阅读