What is the simplest/cleanest way to implement singleton pattern in JavaScript?
I needed several singletons with:
and so this was what I came up with:
createSingleton ('a', 'add', [1, 2]);
console.log(a);
function createSingleton (name, construct, args) {
window[name] = {};
window[construct].apply(window[name], args);
window[construct] = null;
}
function add (a, b) {
this.a = a;
this.b = b;
this.sum = a + b;
}
args must be Array for this to work so if you have empty variables, just pass in []
I used window object in the function but I could have passed in a parameter to create my own scope
name and construct parameters are only String for window[] to work but with some simple type-checking, window.name and window.construct are also possible.
You can do it with decorators like in this example below for TypeScript:
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
Then you use your singleton like this:
var myInstance = YourClass.singleton();
As of this writing, decorators are not readily available in JavaScript engines. You would need to make sure your JavaScript runtime has decorators actually enabled or use compilers like Babel and TypeScript.
Also note that singleton instance is created "lazy", i.e., it is created only when you use it for the first time.
The clearest answer should be this one from the book Learning JavaScript Design Patterns by Addy Osmani.
var mySingleton = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() {
// Singleton
// Private methods and variables
function privateMethod(){
console.log( "I am private" );
}
var privateVariable = "Im also private";
var privateRandomNumber = Math.random();
return {
// Public methods and variables
publicMethod: function () {
console.log( "The public can see me!" );
},
publicProperty: "I am also public",
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
})();
How about this way, just insure the class can not new again.
By this, you can use the instanceof
op, also, you can use the prototype chain to inherit the class,it's a regular class, but can not new it,if yuu want to get the instance just use getInstance
function CA()
{
if(CA.instance)
{
throw new Error('can not new this class');
}else{
CA.instance = this;
}
}
/**
* @protected
* @static
* @type {CA}
*/
CA.instance = null;
/** @static */
CA.getInstance = function()
{
return CA.instance;
}
CA.prototype =
/** @lends CA#*/
{
func: function(){console.log('the func');}
}
// initilize the instance
new CA();
// test here
var c = CA.getInstance()
c.func();
console.assert(c instanceof CA)
// this will failed
var b = new CA();
If you don't want to expose the instance
member, just put it into a closure.
I believe this is the simplest/cleanest and most intuitive way though it requires ES7:
export default class Singleton { static instance; constructor(){ if(instance){ return instance; } this.state = "duke"; this.instance = this; } }
The source code is from: adam-bien.com
What's wrong with this?
function Klass() {
var instance = this;
Klass = function () { return instance; }
}