Definition: Ensures that a class has only one instance and provides a global access point to access it

Core: Ensures that there is only one instance and provides global access

The singleton pattern is a common pattern, and there are some objects that we usually need only one, such as thread pool, global cache, window object in browser, and so on. Singleton patterns are also very useful in JavaScript development. Imagine that when we click the login button, there is a login float window that is unique and will only be created once, no matter how many times we click the login button. This login float window is suitable for singleton mode

Implement the singleton pattern

Implementing a standard singleton pattern is nothing more than a variable that indicates whether an object has been created for a class and, if so, returns the previously created object the next time an instance of the class is fetched

var Singleton = function( name ){
    this.name = name;
    / / instance
    this.instance = null;
};
Singleton.prototype.getName = function(){
    console.log(this.name)
}; 
Singleton.getInstance = function( name ){
    // If there is an instance, skip it
    if(!this.instance ){
        this.instance = new Singleton( name );
    }
    return this.instance;
}; 
var a = Singleton.getInstance( 'sven1' );
var b = Singleton.getInstance( 'sven2' );

console.log( a === b ); // true
a.getName(); // sven1
b.getName(); // sven1
Copy the code

or

var Singleton = function( name ){
    this.name = name;
};
Singleton.prototype.getName = function(){
    console.log(this.name)
};
// Use closures to hold instance objects
Singleton.getInstance = (function(){
    var instance = null;
    return function( name ){
        if ( !instance ){
       	    instance = new Singleton( name );
        }
        return instance;
   }
})();

console.log( a === b ); // true
a.getName(); // sven1
b.getName(); // sven1
Copy the code

The problem with using Singleton. GetInstance to get the unique object of the Singleton class is that it increases the “opacity” of the class. Users of the Singleton class must know that this is a Singleton class. You must use singleton.getInstance to get an object, not new

Implement the singleton pattern with a proxy

// constructor
var CreateSingleton = function( name ){
    this.name = name;
    this.init(); 
}
CreateSingleton.prototype.init = function(){
    // The initialization method is performed here
    console.log( this.name )
} 
/** * introduces the proxyClass proxyClass to manage singletons * this uses self-executing anonymous functions and closures to encapsulate variables inside closures */
var proxyClass = (function(){
    var instance; 
    return function( name ){
         // Skip if there are instances
         if ( !instance ){
         	instance = new CreateSingleton( name );
         } 
         return instance;
    }
})(); 

var a = new proxyClass('singleton1'); 
var b = new proxyClass('singleton2');
console.log( a === b ); // true
Copy the code

By introducing proxies, we can retrieve singletons directly from new and transfer the logic responsible for managing singletons to the proxyClass, proxyClass, so that the CreateSingleton becomes a normal class that can be combined with the proxyClass to achieve the singleton effect

The singleton pattern in JavaScript

The implementations of the singleton pattern mentioned earlier are more like those in traditional object-oriented languages, where singleton objects are created from “classes.” This is a natural thing to do in a class-centric language. In Java, for example, if you need an object, you must first define a class from which the object is always created





But JavaScript is actually a classless language. The way to create an object in JavaScript is very simple. You just need to create a variable object. This is like taking a bath in cotton-padded clothes

The core of the singleton pattern is to ensure that there is only one instance and to provide global access

var a = {};
Copy the code

Then we get a little confused. In that case, let’s just create a unique variable, but global variables have a lot of problems. They can cause namespace pollution, so we need to reduce naming pollution in several ways

① Use namespaces

Proper use of namespaces does not eliminate global variables, but it can reduce the number of global variables

var namespace = {
    a: function(){
       alert (1);
    },
    b: function(){
       alert (2); }};Copy the code

Use closures to encapsulate private variables

This approach encapsulates some variables inside a closure, exposing only interfaces to communicate with the outside world

The __name and __age private variables are wrapped in the scope generated by the closure. They are not accessible outside the closure. This avoids global command contamination
var user = (function(){
    var __name = 'sven',
        __age = 29;
    return {
        getUserInfo: function(){
            return __name + The '-'+ __age; }}}) ();Copy the code

Inert singleton

Lazy singletons are instances of objects that are created only when needed

GetInstance is always created when we call singleton.getInstance, not when the page is ready to load, as follows:

Singleton.getInstance = (function(){
    var instance = null;
    return function( name ){
        if ( !instance ){
            instance = new Singleton( name );
        }
        return instance;
   }
})();
Copy the code

However, this is a “class-based” singleton pattern, which is not applicable in JavaScript. Next, I will show you a lazy singleton in JS combined with global variables

var getSingle = function(fn){
  var result
  return function(){
    return result || ( result = fn.apply(this.arguments))}}var createLoginLayer = function(){
  var div = document.createElement( 'div' )
  div.innerHTML = 'I'm logging in to the floating window.'
  div.style.display = ' none '
  document.body.appendChild( div )
  return div
}
// Prerender floating window
var LoginLayer = getSingle( createLoginLayer )
// Open the floating window
LoginLayer().style.display = 'block'
// Close the floating window
LoginLayer().style.display = 'none'
Copy the code

But now that it’s 2020 and frameworks are in use, it’s rare to be able to manipulate the DOM completely directly, but design patterns can still be used

Lazy singletons are used in Vue

Lazy singletons have two advantages:

Singleton – created only once

Lazy – only load “cached”

So in Vue we can optimize code like this:

① V-IF active control is not loaded for the first time and is loaded only when needed

② V-show defaults to true, and controls show and hide only when v-if is true

<template>
  <div>
    <el-button @click="isLoad = true">Click to start loading the dialog</el-button>
    <! -- Element's dialog box component -->
    <el-dialog
      title="Tip"
      :visible.sync="dialogVisible"
      width="30%"
      v-if="isLoad"
    >
      <span>This is a piece of information</span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">Take away</el-button>
        <el-button type="primary" @click="dialogVisible = false"
          >Determine < / el - button ></span>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isLoad:false.dialogVisible: false}; }};</script>
Copy the code

The el-Dialog is loaded by clicking isLoad to true, and the hiding and display of the El-Dialog is controlled by v-show. This optimization is suitable for some of the most resource-intensive functions that are not commonly used by users, resulting in meaninglessly long load times

The singleton pattern in Vuex

Introducing Vuex into the project:

// Introduce the vuex plugin
import Vuex from 'vuex'
// Install vuex plug-in
Vue.use(Vuex)

// Create an instance of vuex
var store =  new Vuex.Store({})
// Inject store into Vue instance
new Vue({
    el: '#app',
    store
})
Copy the code

Install the Vuex plug-in by calling vue.use (). The Vuex plug-in is an object that internally implements a install method, which is called when the plug-in is installed to inject the Store into the Vue instance

let Vue // Vue has the same function as instance above.export function install (_Vue) {
  // Determine if the incoming Vue instance object has been installed (with a unique state)
  if (Vue && _Vue === Vue) {
    if(process.env.NODE_ENV ! = ='production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.')}return
  }
  // If not, install a unique Vuex for the Vue instance object
  Vue = _Vue
  // Write the Vuex initialization logic into the Vue hook function
  applyMixin(Vue)
}
Copy the code

The above is Vuex source singleton pattern implementation method. In this way, it is guaranteed that a Vue instance (i.e. a Vue application) will only be installed once for the Vuex plug-in, so each Vue instance will have only one global Store

reference

JavaScript Design Patterns and Development Practices: An Exploration

JavaScript lazy singleton and VUE performance optimization applications

JavaScript design pattern — singleton pattern

For any errors or better use of vUE singleton mode, please leave a comment in the comments section. Thank you for reading!!

Design patterns complement language deficiencies

Peter Norvig –