• The singleton pattern is defined as:Ensure that a class has only one instance and provide a global access point to access it.
  • How it works: A variable is used to indicate whether an object has been created for a class, and if so, the next time an instance of the class is fetched, the previously created object is returned

1. Singleton mode

// The first way
var Singleton1 = function (name) {
  this.name = name;
  this.instance = null;
};

Singleton1.getInstance = function (name) {
  if (!this.instance) {
    this.instance = new Singleton1(name);
  }
  return this.instance;
};

var a = Singleton1.getInstance('sven1');
var b = Singleton1.getInstance('sven2');

alert(a === b);   //true

// The second way

var Singleton2 = function (name) {
  this.name = name;
}

Singleton2.getInstance = (function () {
  var instance = null;
  return function (name) {
    if(! instance) { instance =new Singleton2(name);
    }
    return instance;
  }
})();

var c = Singleton2.getInstance('jun');
var d = Singleton2.getInstance('bin');

alert(c === d);   //true
Copy the code
  • Disadvantages of the above implementation: This approach is relatively simple, but one problem is that it increases the “opacity” of the class. Users of the Singleton class must know that this is a Singleton class. Instead of fetching objects using new XXX, we use Singleton.getInstance

2. Transparent singleton pattern

  • Our goal now is to implement a “transparent” singleton class from which users can create objects just like any other normal class. In the following example, we will use the CreateDiv singleton class, which is responsible for creating a unique DIV node on the page
var CreateDiv = (function () {

  var instance;

  var CreateDiv = function (html) {
    if (instance) {
      return instance;
    }
    this.htme = html;
    this.init();

    return instance = this;
  };

  CreateDiv.prototype.init = function () {
    var div = document.createElement('div');
    div.innerHTML = this.html;
    document.body.appendChild(div);
  };

  returnCreateDiv; }) ();var a = new CreateDiv('sven1');
var b = new CreateDiv('sven2');

console.log(a === b);//true
Copy the code
  • Cons: To wrap instance, we use self-executing anonymous functions and closures, and let the anonymous function return the real Singleton constructor, which adds some complexity to the program

3. The agent implements the singleton pattern

var CreateDiv = function (html) {
  this.html = html;
  this.init();
};

CreateDiv.prototype.init = function () {
  var div = document.createElement('div');
  div.innerHTML = this.html;
  document.body.appendChild(div);
};

// Next, introduce the proxy class
var ProxySingtonCreateDiv = (function () {

  var instance;
  return function (html) {
    if(! instance) { instance =new CreateDiv(html);
    }
    return instance;
  }
})();

var c = new ProxySingtonCreateDiv('kobe');
var d = new ProxySingtonCreateDiv('curry');

console.log(c === d); //true
Copy the code

4. 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 really a class-free language, and for that reason, the concept of a singleton pattern doesn’t make sense. The way to create an object in JavaScript is very simple, since we only need a “unique” object, why create a “class” for it? This is akin to taking a shower in cotton-padded clothes, and the traditional singleton implementation doesn’t work in JavaScript.

  • The core of the singleton pattern is to ensure that there is only one instance and to provide global access.
4.1 Lazy singleton
  • Lazy singletons are instances of objects that are created only when needed. (Lazy singletons are the focus of the singleton pattern)
// Lazy singleton pattern based on class
Singleton.getInstance = (function () {
  var instance = null;
  return function (name) {
    if(! instance) { instance =new Singleton(name);
    }
    returninstance; }; }) ();Copy the code
  • Example: The DOM is created when the button is clicked, and it conforms to the singleton pattern

 <html>
   <body>
     <button id="loginBtn">The login</button>
   </body>
  <script>

    var createLoginLayer = (function () {
      var div;
      return function () {
      // This code still violates the single responsibility principle,
      // The logic for creating objects and managing singletons is placed in
      // Inside the createLoginLayer object
        if(! div) { div =document.createElement('div');
          div.innerHTML = 'I'm logging in to the floating window.';
          div.style.display = 'none';
          document.body.appendChild(div);
        }
        returndiv; }; }) ();document.getElementById('loginBtn').onclick = function () {
      var loginLayer = createLoginLayer();
      loginLayer.style.display = 'block';
    };

   </script>
 </html>
Copy the code

We need to put the same part of the isolated, regardless of the first to create a div and create an iframe how much difference, the management logic of singleton is actually can abstract away completely, this logic is always the same: to logo ever created object with a variable, if it is, in direct return next time this has created a good object.

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
}

var createSingleLayer = getSingle(createLoginLayer)

document.getElementById('loginBtn').onclick = function () {
  var loginLayer = createLoginLayer()
  loginLayer.style.display = 'block'
}

// Create a unique iframe to dynamically load third-party pages:
var createSingleIframe = getSingle(function () {
  var iframe = document.createElement('iframe')
  document.body.appendChild(iframe)
  return iframe
})
document.getElementById('loginBtn').onclick = function () {
  var loginLayer = createSingleIframe()
  loginLayer.src = 'http://baidu.com'
}
Copy the code