JavaScript design patterns that front-end engineers must know (with detailed mind map and source code)

Preface

Design mode is a necessary skill for programmers to advance and advanced, and it is also a touchstone for judging the work experience and ability of an engineer. Design mode is the condensing and summary of programmers' years of work experience, which can optimize the code to a greater extent and the existing code Reasonable refactoring. As a qualified front-end engineer, learning design patterns is another way to summarize and reflect on your own work experience, and it is also an important means to develop high-quality, highly maintainable, and scalable code.

We are familiar with several major frameworks of the Golden Classic, such as jquery, react, and vue. There are also a large number of design patterns, such as observer mode, proxy mode, singleton mode, etc., so as an architect, design patterns must be mastered.

During the interview process of middle and senior front-end engineers, the interviewer will also appropriately investigate the job applicant’s understanding of design patterns. Therefore, the author combines years of work experience and learning and exploration to summarize and draw a mind map and a javascript design pattern. The actual case, let us explore Xi together next.

You will gain

  • Singleton mode

  • Constructor pattern

  • Builder mode

  • Agency model

  • Appearance mode

  • Observer mode

  • Strategy mode

  • Iterator mode

text

Let's take a look at the overview first. What can design patterns bring us?


The author summarizes the main benefits of more than a few design patterns give the project brings, such as code that can be decoupled , scalability , reliability , clarity , reusability Next we look at the first of javascript Design Patterns.

1. Singleton mode

1.1 Concept interpretation

Singleton mode: To ensure that a class has only one instance, generally first determine whether the instance exists, if it exists, return directly, if it does not exist, create it and then return, so that you can ensure that a class has only one instance object.

1.2 Role

  • Communication between modules

  • Guarantee the uniqueness of objects of a certain class

  • Prevent variable contamination

1.3 Matters needing attention

  • Use this correctly

  • Closures are easy to cause memory leaks, so unnecessary variables must be cleared in time

  • The cost of creating a new object is higher

1.4 Actual case

The singleton mode is widely used in different programming languages. It is widely used in actual software applications, such as computer task managers, recycle bins, website counters, and multi-threaded thread pool design.

1.5 code implementation


(function(){  // 养鱼游戏  let fish = null  function catchFish() {    // 如果鱼存在,则直接返回    if(fish) {      return fish    }else {      // 如果鱼不存在,则获取鱼再返回      fish = document.querySelector('#cat')      return {        fish,        water: function() {          let water = this.fish.getAttribute('weight')          this.fish.setAttribute('weight', ++water)        }      }    }  }
  // 每隔3小时喂一次水  setInterval(() => {    catchFish().water()  }, 3*60*60*1000)})()

2. Constructor mode

2.1 Concept interpretation

Constructor pattern: Used to create specific types of objects in order to realize the reusability of business logic and functions.

2.2 Function

  • Create a specific type of object

  • Encapsulation of logic and business

2.3 Matters needing attention

  • Pay attention to dividing the boundaries of business logic

  • Cooperate with singleton to realize initialization and other tasks

  • Constructor naming convention, the first letter is capitalized

  • The cost of the new object, putting public methods on the prototype chain

2.4 Actual case

I think the constructor mode is the format of the code, and it is also used to test the programmer's understanding of the business code. It is often used to implement javascript tool libraries, such as lodash and javascript frameworks.

2.5 Code display

function Tools(){
  if(!(this instanceof Tools)){
    return new Tools()
  }
  this.name = 'js工具库'
  // 获取dom的方法
  this.getEl = function(elem) {
    return document.querySelector(elem)
  }
  // 判断是否是数组
  this.isArray = function(arr) {
    return Array.isArray(arr)
  }
  // 其他通用方法...
}
3. 建造者模式

3.1 Concept interpretation

Builder mode: A complex logic or function is realized step by step through organized division of labor.

3.2 Function

  • Distribute to create a complex object or implement a complex function

  • Decoupling the packaging process, no need to pay attention to the details of specific creation

3.3 Matters needing attention

  • Need to be supported by reliable algorithms and logic

  • Expose certain interfaces on demand

3.4 Actual case

The builder mode is actually applied in many fields. The author has written a lot of js plugins before, most of which adopt the builder mode. You can learn and refer to the author's github address Xu Xiaoxi's github. Other cases are as follows:

  • Jquery's ajax package

  • jquery plugin package

  • The design of a specific component of react/vue

3.5 Code display

The author takes a case previously implemented using the builder mode: Canvas entry into actual combat using javascript object-oriented implementation of a graphic verification code, let us use the builder mode to implement a very common verification code plug-in!


// canvas绘制图形验证码(function(){    function Gcode(el, option) {        this.el = typeof el === 'string' ? document.querySelector(el) : el;        this.option = option;        this.init();    }    Gcode.prototype = {        constructor: Gcode,        init: function() {            if(this.el.getContext) {                isSupportCanvas = true;                var ctx = this.el.getContext('2d'),                // 设置画布宽高                cw = this.el.width = this.option.width || 200,                ch = this.el.height = this.option.height || 40,                textLen = this.option.textLen || 4,                lineNum = this.option.lineNum || 4;                var text = this.randomText(textLen);                    this.onClick(ctx, textLen, lineNum, cw, ch);                this.drawLine(ctx, lineNum, cw, ch);                this.drawText(ctx, text, ch);            }        },        onClick: function(ctx, textLen, lineNum, cw, ch) {            var _ = this;            this.el.addEventListener('click', function(){                text = _.randomText(textLen);                _.drawLine(ctx, lineNum, cw, ch);                _.drawText(ctx, text, ch);            }, false)        },        // 画干扰线        drawLine: function(ctx, lineNum, maxW, maxH) {            ctx.clearRect(0, 0, maxW, maxH);            for(var i=0; i < lineNum; i++) {                var dx1 = Math.random()* maxW,                    dy1 = Math.random()* maxH,                    dx2 = Math.random()* maxW,                    dy2 = Math.random()* maxH;                ctx.strokeStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';                ctx.beginPath();                ctx.moveTo(dx1, dy1);                ctx.lineTo(dx2, dy2);                ctx.stroke();            }        },        // 画文字        drawText: function(ctx, text, maxH) {            var len = text.length;            for(var i=0; i < len; i++) {                var dx = 30 * Math.random() + 30* i,                    dy = Math.random()* 5 + maxH/2;                ctx.fillStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';                ctx.font = '30px Helvetica';                ctx.textBaseline = 'middle';                ctx.fillText(text[i], dx, dy);            }        },        // 生成指定个数的随机文字        randomText: function(len) {            var source = ['a', 'b', 'c', 'd', 'e',            'f', 'g', 'h', 'i', 'j',             'k', 'l', 'm', 'o', 'p',            'q', 'r', 's', 't', 'u',            'v', 'w', 'x', 'y', 'z'];            var result = [];            var sourceLen = source.length;            for(var i=0; i< len; i++) {                var text = this.generateUniqueText(source, result, sourceLen);                result.push(text)            }            return result.join('')        },        // 生成唯一文字        generateUniqueText: function(source, hasList, limit) {            var text = source[Math.floor(Math.random()*limit)];            if(hasList.indexOf(text) > -1) {                return this.generateUniqueText(source, hasList, limit)            }else {                return text            }          }    }    new Gcode('#canvas_code', {        lineNum: 6    })})();// 调用new Gcode('#canvas_code', {  lineNum: 6})

4. Agency Mode

4.1 Concept interpretation

Proxy mode: An object controls access to another object through a certain proxy method.

4.2 Function

  • Remote proxy (a local proxy of one object to another)

  • Virtual proxy (for objects that need to create a lot of overhead, such as rendering large web pages, you can use thumbnails instead of real images)

  • Security proxy (protect access to real objects)

  • Cache proxy (some expensive operations provide temporary storage, the next time the operation, if the passed in parameters are the same as before, you can directly return the previously stored operation results)

4.3 Matters needing attention

Using proxies will increase the complexity of the code, so you should use proxies selectively.

actual case

We can use the proxy mode to achieve the following functions:

  • Optimize computing performance through caching proxy

  • Picture placeholder/skeleton screen/preload etc.

  • Merge request/resource

4.4 Code display

Next, we will talk about the application of proxy mode by implementing a calculation buffer.


// 缓存代理function sum(a, b){  return a + b}let proxySum = (function(){  let cache = {}  return function(){      let args = Array.prototype.join.call(arguments, ',');      if(args in cache){          return cache[args];      }
      cache[args] = sum.apply(this, arguments)      return cache[args]  }})()

5. Appearance mode

5.1 Concept interpretation

Facade: Provide a consistent performance for a set of interfaces in the subsystem, making the subsystem easier to use without paying attention to internal complex and cumbersome details.

5.2 Function

  • A certain decoupling of the interface and the caller

  • Create a classic three-tier structure MVC

  • Reduce the dependence and coupling between different subsystems in the development phase to facilitate the iteration and expansion of each subsystem

  • Provide a clear interface for large complex systems

5.3 Matters needing attention

When the appearance mode is continuously called by the developer, it will cause a certain performance loss. This is due to the availability check every time the call is called

5.4 Actual case

We can use the appearance mode to design event binding methods compatible with different browsers and other methods or abstract classes that need to implement interfaces uniformly.

5.5 Code display

Next, we will let everyone understand how to use the appearance mode by implementing an event listening function compatible with different browsers.

function on(type, fn){
  // 对于支持dom2级事件处理程序
  if(document.addEventListener){
      dom.addEventListener(type,fn,false);
  }else if(dom.attachEvent){
  // 对于IE9一下的ie浏览器
      dom.attachEvent('on'+type,fn);
  }else {
      dom['on'+ type] = fn;
  }
}
6. 观察者模式

6.1 Concept interpretation

Observer mode: A one-to-many relationship is defined. All observation objects monitor a subject object at the same time. When the state of the subject object changes, all observer objects will be notified so that they can automatically update themselves.

6.2 Function

  • There is a dynamic relationship between the target object and the observer, which increases flexibility

  • Support simple broadcast communication, automatically notify all subscribed objects

  • The abstract coupling relationship between the target object and the observer can be extended and reused separately

6.3 Matters needing attention

Observer mode generally needs to be monitored first, and then triggered (in special circumstances, you can also publish first, then subscribe, such as the offline mode of QQ)

6.4 Practical case

The observer pattern is a very classic design pattern, and its main applications are as follows:

  • System message notification

  • Website logging

  • Content subscription function

  • javascript event mechanism

  • Observers such as react/vue

6.5 Code display

Next we use native javascript to implement an observer mode:


class Subject {  constructor() {    this.subs = {}  }
  addSub(key, fn) {    const subArr = this.subs[key]    if (!subArr) {      this.subs[key] = []    }    this.subs[key].push(fn)  }
  trigger(key, message) {    const subArr = this.subs[key]    if (!subArr || subArr.length === 0) {      return false    }    for(let i = 0, len = subArr.length; i < len; i++) {      const fn = subArr[i]      fn(message)    }  }
  unSub(key, fn) {    const subArr = this.subs[key]    if (!subArr) {      return false    }    if (!fn) {      this.subs[key] = []    } else {      for (let i = 0, len = subArr.length; i < len; i++) {        const _fn = subArr[i]        if (_fn === fn) {          subArr.splice(i, 1)        }      }    }  }}
// 测试// 订阅let subA = new Subject()let A = (message) => {  console.log('订阅者收到信息: ' + message)}subA.addSub('A', A)
// 发布subA.trigger('A', '我是徐小夕')   // A收到信息: --> 我是徐小夕

7. Strategy Mode

7.1 Concept interpretation

Strategy mode: The strategy mode reasonably classifies and encapsulates different algorithms so that different algorithms can be replaced with each other without affecting the users of the algorithm.

7.2 Function

  • Different realization, same effect

  • The calling method is the same, which reduces the cost of use and the coupling between different algorithms

  • Separately define algorithm models to facilitate unit testing

  • Avoid a lot of redundant code judgments, such as if else, etc.

7.3 Actual case

  • Achieve more elegant form validation

  • The role scorer in the game

  • Winning and losing algorithms for chess and card games

7.4 Code display

Next, we implement a mode that implements the summation algorithm according to different types to help everyone understand the strategy mode.


const obj = {  A: (num) => num * 4,  B: (num) => num * 6,  C: (num) => num * 8}
const getSum =function(type, num) {  return obj[type](num)}

8. Iterator mode

8.1 Concept interpretation

Iterator pattern: Provides a method to sequentially access each element in an aggregate object, and the user does not need to care about the internal representation of the method.

8.2 Function

  • Provide a unified interface for traversing different collections

  • Protect the original collection but provide external access to internal elements

8.3 Practical case

The most common case of the iterator pattern is the array traversal method such as forEach, map, reduce.

8.4 Code display

Next, I use a traversal function that I encapsulated to let everyone better understand the use of the iterator pattern. This method can not only traverse arrays and strings, but also traverse objects. _.forEach(collection, [iteratee=_. identity)) method is also a typical application of strategy mode.


function _each(el, fn = (v, k, el) => {}) {  // 判断数据类型  function checkType(target){    return Object.prototype.toString.call(target).slice(8,-1)  }
  // 数组或者字符串  if(['Array', 'String'].indexOf(checkType(el)) > -1) {    for(let i=0, len = el.length; i< len; i++) {      fn(el[i], i, el)    }  }else if(checkType(el) === 'Object') {    for(let key in el) {      fn(el[key], key, el)    }  }}

At last

If you want to understand the complete mind map of this article, more H5 games , webpack , node , gulp , css3 , javascript , nodeJS , canvas data visualization and other front-end knowledge and actual combat, welcome to join us in the public account "Interesting Frontend" to learn and discuss , To jointly explore the front-end boundary.

Dooring update log

Welcome to follow the public account below to get more front-end knowledge and join the learning community:

Reply to Webpack to get a single-page/multi-page scaffolding mind map with webpack4.0

Reply to lodash , you will get the Chinese mind map of lodash API translated by myself

Reply to the  learning path , and get a mind map of the front-end learning path of the author’s years of experience

Talk about the front end

Vue, React, applet, Node 

 

Front-end  algorithm|performance|architecture|security

Guess you like

Origin blog.csdn.net/KlausLily/article/details/109554789