introduce
Starting from this chapter, we will gradually introduce the various design pattern implementations used in JavaScript. Here I will not introduce too much theories of the pattern itself, but will only focus on implementation. OK, officially start.
In the eyes of traditional development engineers, a singleton is to ensure that a class has only one instance. The implementation method is generally to first determine whether the instance exists or not. If it exists, it will be directly returned, and if it does not exist, it will be created and then returned, which ensures that a class has only one instance object. In JavaScript, singleton acts as a namespace provider, providing a unique access point from the global namespace to access the object.
text
In JavaScript, there are many ways to implement singletons. The easiest way is to use the literal object, which can contain a large number of properties and methods:
The code copy is as follows:
var mySingleton = {
property1: "something",
property2: "something else",
method1: function () {
console.log('hello world');
}
};
If you want to extend the object later, you can add your own private members and methods, and then use a closure to encapsulate these variables and function declarations inside it. Only the public members and methods you want to expose are exposed. The sample code is as follows:
The code copy is as follows:
var mySingleton = function () {
/* Declare private variables and methods here*/
var privateVariable = 'something private';
function showPrivate() {
console.log(privateVariable);
}
/* Public variables and methods (private variables and methods can be accessed) */
return {
publicMethod: function () {
showPrivate();
},
publicVar: 'the public can see this!'
};
};
var single = mySingleton();
single.publicMethod(); // output 'something private'
console.log(single.publicVar); // Output 'the public can see this!'
The above code is pretty good, but what if we want to do it only initialize when we use it? For the purpose of saving resources, we can initialize these codes in another constructor, as follows:
The code copy is as follows:
var Singleton = (function () {
var instantiated;
function init() {
/*Define singleton code here*/
return {
publicMethod: function () {
console.log('hello world');
},
publicProperty: 'test'
};
}
return {
getInstance: function () {
if (!instantiated) {
instantiated = init();
}
return instantiated;
}
};
})();
/*Calling a public method to get the instance:*/
Singleton.getInstance().publicMethod();
I know how to implement singletons, but what kind of scenario is the best scenario for singletons to be used? In fact, singletons are generally used for communication coordination between various modes between systems. The following code is the best practice for a singleton:
The code copy is as follows:
var SingletonTester = (function () {
//Parameter: A set of parameters passed to a singleton
function Singleton(args) {
//Set the args variable to the received parameter or be empty (if not provided)
var args = args || {};
//Set name parameters
this.name = 'SingletonTester';
//Set the value of pointX
this.pointX = args.pointX || 6; //Get from the received parameters, or set to the default value
//Set the value of pointY
this.pointY = args.pointY || 10;
}
//Instance container
var instance;
var _static = {
name: 'SingletonTester',
// Method to get instance
//Return the Singleton instance
getInstance: function (args) {
if (instance === undefined) {
instance = new Singleton(args);
}
return instance;
}
};
return _static;
})();
var singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // Output 5
Other implementation methods
Method 1:
The code copy is as follows:
function Universe() {
// Determine whether there is an instance
if (typeof Universe.instance === 'object') {
return Universe.instance;
}
// Other content
this.start_time = 0;
this.bang = "Big";
// cache
Universe.instance = this;
// Implicitly return this
}
// test
var uni = new universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
Method 2:
The code copy is as follows:
function Universe() {
// Cache instance
var instance = this;
// Other content
this.start_time = 0;
this.bang = "Big";
// Rewrite the constructor
Universe = function () {
return instance;
};
}
// test
var uni = new universe();
var uni2 = new Universe();
uni.bang = "123";
console.log(uni === uni2); // true
console.log(uni2.bang); // 123
Method 3:
The code copy is as follows:
function Universe() {
// Cache instance
var instance;
// Reconstruct the function
Universe = function Universe() {
return instance;
};
// Post-processing of prototype properties
Universe.prototype = this;
// Example
instance = new Universe();
// Reset the constructor pointer
instance.constructor = Universe;
// Other functions
instance.start_time = 0;
instance.bang = "Big";
return instance;
}
// test
var uni = new universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
// Add prototype properties
Universe.prototype.nothing = true;
var uni = new universe();
Universe.prototype.everything = true;
var uni2 = new Universe();
console.log(uni.nothing); // true
console.log(uni2.nothing); // true
console.log(uni.everything); // true
console.log(uni2.everything); // true
console.log(uni.constructor === Universe); // true
Method 4:
The code copy is as follows:
var Universe;
(function () {
var instance;
Universe = function Universe() {
if (instance) {
return instance;
}
instance = this;
// Other content
this.start_time = 0;
this.bang = "Big";
};
} ());
//Test code
var a = new Universe();
var b = new Universe();
alert(a === b); // true
a.bang = "123";
alert(b.bang); // 123