I plan to learn Javascript systematically recently

Design patterns, so that they can be encapsulated according to the ideas provided by design patterns in the development of problems, which can improve the development efficiency and can avoid many unknown problems in advance.

Start with the basic singleton pattern

What is the singleton pattern

The singleton pattern, in terms of name splitting, singleton refers to a single instance. An instance is an instance, which means that instances created from a class multiple times always return the same instance. It limits a class to only one instance. The singleton pattern is primarily designed to solve the problem of object creation. Singleton pattern features:

1. A class has only one instance

2. Provide a unique access interface externally

In some class-centric languages, such as Java, you must first define a class for each object you create, from which the object is created. Js is a class-free language. The method of creating objects in JS is very simple. You do not need to define the class to create objects.

The singleton pattern is a common pattern in JS, such as the Window object provided in the browser, and the Math object that handles numbers.

Implementation of singleton pattern

1

Object literals

The simplest way to implement a singleton in JS is to create object literals, which can contain multiple properties and methods.

var mySingleton = {

attr1:1,

attr2:2,

method:function (){

    console.log("method");  
    
}
Copy the code

}

To access properties and methods in the object, you must use the mySingleton object, which provides a unique access interface.

2

Privatize using closures

Extend the mySingleton object to add private properties and methods, encapsulate variable and function declarations inside it in the form of closures, and expose only public members and methods.

var mySingleton = (function (){

// Private variablesCopy the code

Var privateVal = ‘I am private ‘;

// Private functionCopy the code

function privateFunc(){

Console. log(' I'm a private function ');Copy the code

}

return { attr1:1, attr2:2, method:function (){ console.log("method"); privateFunc(); }}Copy the code

}) ()

Wrapping privateVal and privateVal in the scope created by the closure makes them inaccessible to the outside world, which avoids global naming contamination.

3

Inert singleton

Whether you create a singleton using object literals or private closures, it is created as soon as the script loads.

Sometimes pages may not use this singleton, which can be a waste of resources. In this case, the best way to handle this is to use lazy singletons, which are initialized when the singleton is needed.

var mySingleton = (function (){

Function init(){var privateVal = 'I'm private '; Function privateFunc(){console.log(' I'm a private function '); } return { attr1:1, attr2:2, method(){ console.log("method"); privateFunc(); }}} var instance = null; Return {getInstance (){// if(! instance){ instance = init(); } // if instance has a value, return instance; }}Copy the code

}) ();

// Get the singleton

var singletonObj1 = mySingleton.getInstance();

var singletonObj2 = mySingleton.getInstance();

console.log( singletonObj1 === singletonObj2 ); //true

After the program executes, the code to create the singleton is wrapped in the init function, exposing only the function getInstance to get the singleton. Call mysingleton.getInstance () to get the singleton when needed, and use instance to cache the object. Call mysingleton.getInstance () again to get the same object. This saves resources by not creating multiple objects through a function.

4. Use constructors

We can use constructors to create singletons:

function mySingleton(){

If (mysingleton.instance) {return mysingleton.instance; } // When instantiated for the first time, mysingleton.instance = this;Copy the code

}

mySingleton.prototype.otherFunc = function (){

Console. log(" Other methods on prototype ");Copy the code

}

var p1 = new mySingleton();

var p2 = new mySingleton();

console.log( p1 === p2 ); //true

Mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance: mysingleton. instance This is consistent with the singleton pattern: a class can have only one instance.

One problem with this is that it exposes the mysingleton.instance property that can be accessed from the cache instance, and the value of this property can be changed:

var p1 = new mySingleton();

// Change the value of mysingleton.instance

//mySingleton.instance = null;

/ / or

mySingleton.instance = {};

var p2 = new mySingleton();

console.log( p1 === p2 ); //false

Changed the mySingleton. The instance value, and then through the new calls the constructor to create an instance, and create a new object, so it’s not the same object, p1 and p2 violated the singleton pattern a class can have only one instance.

An instance in a closure

Instead of using the static attribute of the function to cache the instance, rewrite the constructor:

function mySingleton(){

Var instance = this; MySingleton = function (){return instance; } // other code instance.userName = "ABC ";Copy the code

}

mySingleton.prototype.otherFunc = function (){

Console. log(" Other methods on prototype ");Copy the code

}

var p1 = new mySingleton();

var p2 = new mySingleton();

console.log( p1 === p2 ); //true

After the first instance is created using a new call to the function, create instance in the function to cache the instance and rewrite mySingleton as another function. If the function is called again using new, the closure property returns the cached object, so p1 and p2 are the same object.

This also ensures that a class returns only one instance, but note that the constructor called the second time using new is an anonymous function because mySingleton has been overwritten: mySingleton

// On the second new mySingleton() the anonymous function is the real constructor

mySingleton = function (){

return instance;    
Copy the code

} mysingleton.prototype: mysingleton.prototype: mysingleton.prototype: mysingleton.prototype: mysingleton.prototype: mysingleton.prototype

var p1 = new mySingleton();

// Add attributes to the mySingleton prototype again

MySingleton. Prototype. AddAttr = “I am the newly added property”;

var p2 = new mySingleton();

console.log(p2.addAttr); //undefined

Object P2 access property addAttr was not found. An instance constructed from a constructor does not have access to the methods or properties on the prototype, which is a mistake and needs to be improved.

function mySingleton(){

var instance; MySingleton = function (){return instance; MySingleton. Prototype = this; / / the constructor to rewrite the constructor mySingleton. After the prototype. The constructor = mySingleton; Instance = new mySingleton; // Other code instance.userName = "ABC "; Return instance; return instance;Copy the code

}

mySingleton.prototype.otherFunc = function (){

Console. log(" Other methods on prototype ");Copy the code

}

var p1 = new mySingleton();

// Add attributes to the mySingleton prototype again

MySingleton. Prototype. AddAttr = “I am the newly added property”;

var p2 = new mySingleton();

console.log(p2.addAttr); //’ I am a newly added property ‘

console.log( p1 === p2 ); //true

The above code does a few things:

The list of numbers overwrites the mySingleton function to be anonymous

Rewrite the mySingleton prototype to create an instance through New for the first time

Constructor refers back to mySingleton because of rewriting prototype

Explicitly returns the instance constructed by the overwritten mySingleton constructor

The mySingleton constructor returns the same object no matter how many times you call it with new, and they all share the same stereotype.

Practice the singleton pattern

1

Using namespaces

According to the above, creating an object in JS is a singleton, putting a class of methods and properties in the object, all accessed through the provided global object.

var mySingleton = {

attr1:1,
attr2:2,
method:function (){
    console.log("method");    
}
Copy the code

} for example, to add a property to this object: mysingleton.width = 1000; // Add an attribute

// Adding a method overwrites the original method

mySingleton.method = function(){};

If this method of adding attributes often runs the risk of being overwritten in a multi-person collaboration, use the namespace approach.

/ A classmate

mySingleton.a = {};

mySingleton.a.method = function(){}

/ / access

mySingleton.a.method();

/ / B class

mySingleton.b = {};

mySingleton.b.method = function(){}

/ / access

mySingleton.b.method();

All in their own namespace, the chance of overwriting will be small.

You can encapsulate a generic method for creating namespaces on the fly, so you only need to call a function when a separate namespace is needed.

mySingleton.namespace = function(name){

var arr = name.split("."); Var currentObj = mySingleton; for( var i = 0; i < arr.length; I++){// if the object does not exist, the assignment adds the attribute if(! currentObj[arr[i]]){ currentObj[arr[i]] = {}; CurrentObj = currentObj[arr[I]]} currentObj[arr[I]]}Copy the code

}

// Create a namespace

mySingleton.namespace(“bom”);

mySingleton.namespace(“dom.style”);

The above method of calling a function to generate a namespace is equivalent to:

mySingleton.bom = {};

mySingleton.dom = {};

mySingleton.dom.style = {};

2

Singleton login box

Use object oriented to achieve a login box, click the login button after the login box is append to the page, click close will be removed from the login box from the page, so frequent DOM operation is unreasonable and not necessary.

Just hide the login box when you click close, and after clicking the button again, just show. Put only one button on the page:

Js:

function Login(){

var instance;

Login = function(){
    return install;
}

Login.prototype = this;
install = new Login;
install.init();
return install;
Copy the code

}

Login.prototype.init = function(){

// Get the Login element this.login = this.createhtml (); document.body.appendChild(this.Login); // Bind the event this.adDevent ();Copy the code

} Login.prototype.createHtml = function(){

var LoginDiv = document.createElement("div"); LoginDiv.className = "box"; Var HTML = '<input type="button" value=" innerHTML "class="close" /><p> return LoginDiv;Copy the code

} Login.prototype.addEvent = function(){

var close = this.Login.querySelector(".close");
var _this = this;
close.addEventListener("click",function(){
    _this.Login.style.display = 'none';
})
Copy the code

} Login.prototype.show = function(){

this.Login.style.display = 'block';
Copy the code

} // Click the button on the page

var loginBtn = document.querySelector(“#loginBtn”);

loginBtn.onclick = function(){

var login = new Login(); Login.show ();Copy the code

}

The above code is implemented according to the use constructor of the singleton pattern. This generates one object at the beginning, and the same object is used all the time.

conclusion

The singleton pattern is a very useful pattern, especially the lazy singleton technique, where objects are created when appropriate and only one object is created, thus reducing unnecessary memory consumption.

I am learning design patterns, welcome to pat brick correction if not correct.

Subscription ID: Miaovclass

Pay attention to miaowei subscription number: “Miaowei front end”, to bring you high-quality front-end technology dry goods;