Singleton pattern [javascript design pattern]

Is it true to learn from time to time? —— Confucius'The Analects of Confucius

The core of the singleton pattern is to ensure an instance and provide global access.

First, the singleton pattern requires only one instance, and second, the instance is accessible globally. For example, I wrote this page during my internship:


Paste_Image.png


This box pops up when you click on the email to get the latest installation package. Obviously, this box only needs to be created once, so we can write the following code:

// html
        <button class="J-popup">btn</button>
// js
        var popup = (function () {
            var div = document.createElement('div');
            div.innerHTML = 'I am a frame.';
            div.style.display = 'none';
            document.body.appendChild(div);
            return div;
        })();

        document.getElementsByTagName('J-popup').onclick = function () {
            popup.style.display = 'block';
        }

Although this method conforms to the definition of the singleton mode, maybe we will not click the button to get the installation package when we enter this page, then the dom node will be wasted, so it will be created lazily. The modified code is as follows:

      var popup = (function () {
            var div;
            return function () {
                if (!div) {
                    div = document.createElement('div');
                    div.innerHTML = 'I am a frame.';
                    div.style.display = 'none';
                    document.body.appendChild(div);
                }
                return div;
            }
        })();

        document.getElementsByTagName('J-popup').onclick = function () {
            var popupInstance = popup();
            popupInstance.style.display = 'block';
        }

ok, this is a perfect singleton practice, but the above code violates the principle of single responsibility, which leads to a problem: if I need to create another box different from div, such as iframe, I need to copy the popup function again and change it. Take a look at the internal code, don't repeat you self!!!
The reason is that we put the logic of creating and managing objects in the popup function, so all we have to do is separate them:

// Define a function that generates a singleton object:
        var getSingle = function (fn) {
            var instance;
            return function () {
                return instance || ( instance = fn.apply(this, arguments) );
            }
        }

Now you can happily create a single example, such as the bullet box above, which can be as follows:

       var popup = function () {
           var div = document.createElement('div');
           div.innerHTML = 'I am a frame.';
           div.style.display = 'none';
           document.body.appendChild(div);
           return div;
       };

       var popupFactory = getSingle(popup);

       document.getElementsByTagName('J-popup').onclick = function () {
           var popupInstance = popupFactory();
           popupInstance.style.display = 'block';
       }

If you want to create other singletons, just copy popup and throw it to getSingle.

It suddenly occurred to me that the first requirement of the internship is to write a page managed by a designer, which can be simplified into a model of dynamically adding data to the page list through ajax. Each item in the list needs to add click events. Under the premise of using event proxy, click events only need to be rendered when the list is first rendered. Bind it once. But we don't want to judge if the list is currently rendered for the first time. With jquery, we can bind one event to the node:

       var bindEvent = function () {
           $('.list').one('click', function () {
               console.log('click');
           });
       }
       var render = function () {
           console.log('Rendering List');
           bindEvent();
       }
       render();
       render();
       ......

The same effect can be achieved with the help of the getSingle() function we just implemented:

      var bindEvent = getSingle(function () {
           document.getElementsByTagName('list')[0].onClick = function () {
               console.log('click');
           }
           return true;
       });
       var render = function () {
           console.log('Rendering List');
           bindEvent();
       }
       render();
       render();
       ......

ok, that's all. Tomorrow evening, we'll continue our strategy model and welcome our friends to communicate with us.^^

Keywords: JQuery

Added by Sandip on Mon, 01 Jul 2019 23:26:43 +0300