Javascript design pattern prototype mode details

Javascript design pattern prototype mode details

1. Prototype mode

The prototype pattern is used to improve performance, reduce memory usage, and reuse code by sharing the properties and methods of an object prototype when creating an object.

Example 1

function Person(name) {
  this.name = name;

  this.config = {
    a: "1",
    b: "2",
  };

  this.hello = function () {
    console.info("hello");
  };
}

If you need to create 100 instances using the above code, you will need to create 100 config and 100 hello , and these two things are exactly the same in each instance.

Therefore, we can perform oil optimization by extracting common codes.

const config = {
  a: "1",
  b: "2",
};
const hello = function () {
  console.info("hello");
};
function Person(name) {
  this.name = name;

  this.config = config;

  this.hello = hello
}

This way, no matter how many Person objects are created, only one config and one hello need to be created. However, there are still problems such as global variables being polluted, config being modified by mistake, Person being highly coupled with other codes, and difficulty in code expansion and maintenance.

Therefore, optimization can be performed through prototyping.

function Person() {}
var p = new Person();


The prototype diagram of this function when creating an instance is as follows:

Example 2

function Person(name) {
  this.name = name;

  this.config = {
    a: "1",
    b: "2",
  };

  this.hello = function () {
    console.info("hello");
  };
}

//This method will rewrite the prototype, causing the constructor to be lost and become Object().
//You can use Person.prototype.xx=yy to write, or re-specify 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);

The prototype diagram of this function when creating an instance is as follows:

Example 3

function Person(name) {
  this.name = name;

  this.config = {
    a: "1",
    b: "2",
  };

  this.hello = function () {
    console.info("hello");
  };
}

//This method will rewrite the prototype, causing the constructor to be lost and become 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 internal property comparison console.info(pA.hello == pB.hello); //false internal property comparison console.info(pA.say === pB.say); //true prototype method sharing pA.say("qq");
pB.say("qq");
console.info(pA.version === pB.version); //true prototype property sharing console.info(pA.version); //1.0
Person.prototype.version = 2.0; //Modify prototype shared properties console.info(pB.version); //2.0
console.info(new Person().version); //2.0

//Modify the prototype sharing method PersonB.prototype.say = function (arg) {
  console.info(`v2--- ${this.name} say ${arg}`);
};
pB.say("qq");
new Person("Person").say("ww");

Summarize:

js consumes more memory and takes a long time to create objects. You can reduce memory usage by reducing the creation of internal attributes.

The prototype mode uses the prototype feature of the javascript language to share the same properties, thereby reducing memory usage and improving object creation efficiency.

2. Observer Pattern

The observer pattern is used for communication between modules and components by providing a unified pattern for event subscription and event publishing. This achieves decoupling between modules and components and improves the maintainability of the code.

Communication methods between modules and components

Direct reference communication is used between modules and components

const moduleA = {
  say: function (msg) {
    console.info("A say " + msg);
  },

  letBrun: function () {
    //Directly reference moduleB
    moduleB.run();
  },
};

const moduleB = {
  run: function () {
    console.info("B run ");
  },

  letAsay: function () {
    //Directly reference moduleA
    moduleA.say("hello");
  },
};

moduleA.letBrun(); //B Run
moduleB.letAsay(); //A say hello

Parent component communication is used between modules and components

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

Event module realizes communication

function Emitter() {
  this.events = {};
  this.res_oldAction = {}
  this.res_action_events = {}
}

//Subscribe to resourcesEmitter.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)
}

//Unsubscribe resourcesEmitter.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();

//Register events in module A const methodA = (data) => {
  console.info("Module A received food message:");
  console.info(data);
};

emitter.on("food", methodA);

//Register events in module B const methodB = (data) => {
  console.info("Module B receives food message:");
  console.info(data);
};
emitter.on("food", methodB);

//Trigger event in module C emitter.fire("food", "Rice is coming");

//Remove event from module B emitter.remove("food", methodB);

//Trigger the event again in module C emitter.fire("food", "Rice is here again");

The execution results are as follows:

Module A receives the food message:

The meal is here

Module B receives the food message:

The meal is here

Module A receives the food message:

The meal is coming again

Summarize:

There are generally three ways for js component modules to communicate (direct communication, communication through parent components, and communication through event modules). The observer pattern is used for communication between modules and components. It provides a unified pattern for event subscription and event publishing, thereby decoupling modules and components and improving the maintainability of the code.

This is the end of this detailed article about the prototype pattern of Javascript design pattern. For more relevant Javascript prototype pattern content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of JavaScript prototype and examples
  • JavaScript two pictures to understand the prototype chain
  • JavaScript Prototype Details
  • Detailed explanation of JavaScript prototype chain
  • JavaScript prototype and prototype chain details
  • Do you know what JavaScript prototype is?

<<:  Analysis of the operating principle and implementation process of Docker Hub

>>:  Analysis on how to solve the problem of Navicat Premium connecting to MySQL 8.0 and reporting error "1251"

Recommend

Detailed explanation of MySql installation and login

Check if MySQL is already installed in Linux sudo...

Learn Node.js from scratch

Table of contents url module 1.parse method 2. fo...

How to solve the problem that mysql cannot be closed

Solution to mysql not closing: Right-click on the...

A brief discussion on logic extraction and field display of Vue3 in projects

Table of contents Logical Layering Separate busin...

The magic of tr command in counting the frequency of English words

We are all familiar with the tr command, which ca...

MySQL conditional query and or usage and priority example analysis

This article uses examples to illustrate the usag...

Linux automatically deletes logs and example commands from n days ago

1. Delete file command: find the corresponding di...

How to open MySQL binlog log

binlog is a binary log file, which records all my...

Font Treasure House 50 exquisite free English font resources Part 1

Designers have their own font library, which allo...

How to configure two-way certificate verification on nginx proxy server

Generate a certificate chain Use the script to ge...

Analysis of 2 Token Reasons and Sample Code in Web Project Development

Table of contents question: There are 2 tokens in...