Proper way to create singleton ES6 - javascript

What is the proper way to create singleton in JS since ES2015?
I know of many ways such as:
(() => {
let instance;
class Singleton{
constructor(){
instance = instance || this;
}
}
window.Singleton = Singleton; // or sth to export this class
})();
var a = new Singleton();
var b = new Singleton(); // a is the same as b
But it doesn't seem like a good way to use "new" operator with a Singleton class. So my question is whether there is a "proper" way to create a Singleton in ES6

This one seems to work for me:
let instance;
export default class AudioContext {
static getInstance() {
if (!instance) {
instance = {
context:new window.AudioContext() || new window.webkitAudioContext(),
contextCreatedAt: new Date()
}
}
return instance;
}
}
I have created 2 instances of AudioContext at different times. I then checked the time in contextCreatedAt (returns the same) and context === context on the 2 - however please elaborate if I am wrong here.

var a = (function () {
// can put private vars/methods here.
var a = 3;
var b = 5;
var sum = () => a+b;
return {// your singleton object
getSum: sum
// ...
};
}());

Related

How to call a function inside of another function in JavaScript

I looked on whole stack overflow but unfortunately, answer of this question wasn't available so I have a class and inside I have a function:
class DonutMaker {
constructor() {
this.donut_creater = document.getElementById("donut_creater");
this.donut_creater.addEventListener("click", this.donutMaker);
this.auto_clicker = document.getElementById("auto_clicker");
this.auto_clicker.addEventListener("click", this.autoClickerHandler);
}
donutMaker() {
this.selection = document.getElementById("donut_quantity");
this.quantity = this.selection.innerText;
this.updated_quantity = parseInt(this.quantity);
this.updated_quantity = this.updated_quantity + 1;
this.selection.innerText = this.updated_quantity;
}
autoClickerHandler = () => {
this.selection = document.getElementById("donut_quantity");
this.quantity = this.selection.innerText;
this.updated_quantity = parseInt(this.quantity);
this.new_quantity = this.updated_quantity - 1;
if (this.updated_quantity >= 1) {
this.selection.innerText = this.new_quantity;
this.quantity = this.new_quantity;
this.selection2 = document.getElementById("auto_clicker_quantity");
this.auto_clicker_quantity = this.selection2.innerText;
this.auto_clicker_quantity = parseInt(this.auto_clicker_quantity);
this.auto_clicker_quantity_updated = this.auto_clicker_quantity + 1;
this.selection2.innerText = this.auto_clicker_quantity_updated;
this.autoClicker;
} else {
console.log("Not Eligible");
}
};
autoClicker = () => {
console.log("Hello");
// console.log("Auto clicker");
};
}
let obj = new DonutMaker();
//This line at the end of if supposed to call autoClicker but it isnt
this.autoClicker;
It works for me. Two things:
I changed Class to class.
I created an instance of the Student class.
class Student{
a(){
this.b();
}
b(){
console.log("B");
}
}
var student = new Student()
student.a(); // B
JavaScript is case-sensitive so class and Class are considered to be different. The keyword is class. Class would be an unexpected identifier at this position.
A class can be imagined as a blueprint for an instance of that class, similar to how you have a plan for a house. However, for you to be able to work with a class you need to create an object (= an instance of a class) based on said blueprint (= building the actual house using the plan). You will need to use the new keyword for this.
On that instance you can then call the methods you have defined.
// Student class/ blueprint
class Student {
a() {
console.log("a");
this.b();
}
b() {
console.log("b");
}
}
// Create an instance/ object of type Student
const myStudent = new Student();
// Now call method on that instance
myStudent.a();
You should probably get your head around the basic concepts of object oriented programming as explained in this blog post.

Defining your javascript classes with Unique Class names

I'm in the process of building a "custom" javascript library to use across different projects. The library will be built incrementally i.e. the new classes (functions) will be added as the need arises.
The issue which I'm facing is ensuring that my function name doesn't conflict with other developer's function names. I have thought of the following options, and would like the community to find pros and cons of each. Note each option will make use of the prototype pattern to define classes.
Option 1:
Define classes (function) with your company name append infront of it.
Example:
Mycompany.Dept.Js.Class = function()
{
this.Member1 = 3;
}
MyCompany.Dept.Js.ClassA.prototype.PerformOperation = function()
{
return this.Member1;
}
MyCompany.Dept.Js.ClassB = function()
{
this.Member1 = "Test";
}
MyCompany.Dept.Js.ClassB.prototype.GetValue = function(){ return this.Member1;}
Usage:
var obj1 = new MyCompany.Dept.Js.ClassA();
obj1.PerformOperation();
var obj2 = new MyCompany.Dept.Js.ClassA();
obj2.GetValue();
Issue: I have to use the full class name to define my objects.
Option 2: Module Pattern.
var MyCompany.Dept.Js = function() //IIFE
{
var ClassA = function()
{
this.Member1 = 33;
}`
var ClassB = function()
{
this.Member1 = "Test";
}
ClassA.prototype.PerformOperation = function(){//do something;}
ClassB.prototype.GetValue = function(){//do something;}
return {
BuildObject:function(type)
{
if(type=="ClassA") return new ClassA();
if (type == "ClassB") return new ClassB();
}
}
}();
Usage:
var obj1 = MyCompany.Dept.Js.BuildObject("ClassA");
var obj2 = MyCompany.Dept.Js.BuildObject("ClassB");
obj1.PerformOperation();
obj2.GetValue();
Questions:
Do you see any issues with approach # 2. What are some of the cons? Is there any other technique?

How do I augment a method from the superclass in javascript

I have a method in a base class that I want to keep in a subclass, but just add to it. I've found lots of stuff on augmenting classes and objects with properties and methods, but I can't find, or don't understand, how to just augment the method. The worst case scenario is that I would have to paste the entire method of the parent class into the subclass, but that seems like duplicate code... please help
function someObject (){
this.someProperty = 1;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
//do everything the super class has for this property already
return this.someProperty;
}
}
var incrementer = new newObject;
alert (incrementer.incrementProperty()); //I want output to be 2
// parent object
function someObject () {
this.someProperty = 1;
}
// add incrementProperty to the prototype so you're not creating a new function
// every time you instantiate the object
someObject.prototype.incrementProperty = function() {
this.someProperty += 1;
return this.someProperty;
}
// child object
function newObject () {
// we could do useful work here
}
// setup new object as a child class of someObject
newObject.prototype = new someObject();
// this allows us to use "parent" to call someObject's functions
newObject.prototype.parent = someObject.prototype;
// make sure the constructor points to the right place (not someObject)
newObject.constructor = newObject;
newObject.prototype.incrementProperty = function() {
// do everything the super class has for this property already
this.parent.incrementProperty.call(this);
return this.someProperty;
}
var incrementer = new newObject();
alert (incrementer.incrementProperty()); // I want output to be 2
See: http://jsfiddle.net/J7RhA/
this should do, you have to use prototype to have a real concept of oo with javascript
function someObject (){
this.someProperty = 1;
this.propertyOfSomeObject = 0;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
return this.propertyOfSomeObject;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
this.__super__.incrementProperty.apply(this);
return this.propertyOfSomeObject + 1;
}
}
newObject.prototype = new someObject()
newObject.prototype.__super__ = newObject.prototype
var incrementer = new newObject();
alert(incrementer.incrementProperty()); //I want output to be 2
experiment removing incrementProperty from newObject and it will return 1
I usually use the augment library to write classes in JavaScript. This is how I would rewrite your code using augment:
var Foo = Object.augment(function () {
this.constructor = function () {
this.someProperty = 1;
};
this.incrementProperty = function () {
this.someProperty++;
};
});
var Bar = Foo.augment(function (base) {
this.constructor = function () {
base.constructor.call(this);
};
this.incrementProperty = function () {
base.incrementProperty.call(this);
return this.someProperty;
};
});
As you can see since Bar extends Foo it gets Foo.prototype as a parameter (which we call base). This allows you to easily call the base class constructor and incrementProperty functions. It also shows that the constructor itself is just another method defined on the prototype.
var bar = new Bar;
alert(bar.incrementProperty());
The output will be 2 as expected. See the demo for yourself: http://jsfiddle.net/47gmQ/
From this answer:
Overriding functions
Sometimes children need to extend parent functions.
You want the 'child' (=RussionMini) to do something extra. When RussionMini can call the Hamster code to do something and then do something extra you don't need to copy and paste Hamster code to RussionMini.
In the following example we assume that a Hamster can run 3km an hour but a Russion mini can only run half as fast. We can hard code 3/2 in RussionMini but if this value were to change we have multiple places in code where it needs changing. Here is how we use Hamster.prototype to get the parent (Hamster) speed.
// from goog.inherits in closure library
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Hamster = function(name){
if(name===undefined){
throw new Error("Name cannot be undefined");
}
this.name=name;
}
Hamster.prototype.getSpeed=function(){
return 3;
}
Hamster.prototype.run=function(){
//Russionmini does not need to implement this function as
//it will do exactly the same as it does for Hamster
//But Russionmini does need to implement getSpeed as it
//won't return the same as Hamster (see later in the code)
return "I am running at " +
this.getSpeed() + "km an hour.";
}
var RussionMini=function(name){
Hamster.apply(this,arguments);
}
//call this before setting RussionMini prototypes
inherits(RussionMini,Hamster);
RussionMini.prototype.getSpeed=function(){
return Hamster.prototype
.getSpeed.call(this)/2;
}
var betty=new RussionMini("Betty");
console.log(betty.run());//=I am running at 1.5km an hour.

Always return same instance of class

I have this function:
WSConnection: function() {
var instance = new Connection();
return instance;
},
How to I tweak this code (avoid making multiple instances) so that I always get same instance of my Connection class when I call WSConnection();?
May be:
WSConnection: function() {
this.instance = this.instance || new Connection();
return this.instance;
},
Seems to me it is the most compact of all possible solutions..
Create a local variable next to the object that WSConnection is defined on:
var connectionInstance;
// ... {
WSConnection: function() {
return connectionInstance || connectionInstance = new Connection();
},
// ... }
If the object is itself a class then use a "private class" variable instead (this.connectionInstance).
If this use case is specific to the WSConnection function, use a lazily (or non-lazily—suit yourself) initialized global:
var _instance = null; // you can also just create the singleton instance here (eager/non-lazy initialization)
WSConnection: function() {
if (!_instance)
_instance = new Connection();
return _instance;
}
However, if this is an intrinsic quality of the Connection class altogether, turn it into a singleton; there are several ways to do that (e.g. how Java would do it), but since Javascript is a flexible language, I'd do it this way:
Connection = new Connection() // do this at a global scope
Now you will just use Connection to get the single global instance and not new Connection; this also means that you probably won't need the WSConnection function any more. Also, this ensures nothing will be able to create another instance of Connection (if that's what you need, that is)
Create the instance beforehand. You can wrap your containing object in a function, so that the instance variable is not global:
var someobj = (function() {
var instance = new Connection();
return {
WSConnection: function() {
return instance;
}
};
})();
Alternatively use lazy creation, i.e. create it on the first use:
var someobj = (function() {
var instance = null;
return {
WSConnection: function() {
if (instance == null) {
instance = new Connection();
}
return instance;
}
};
})();
WSConnection: (function(){
var instance = null;
return function() {
if( !instance ){
instance = new Connection();
}
return instance;
};
})()

How to make a JavaScript singleton with a constructor without using return?

I currently know two ways to construct singletons in JavaScript. First:
var singleton = {
publicVariable: "I'm public",
publicMethod: function() {}
};
It is perfect except that it does not have a constructor where I could run initialization code.
Second:
(function() {
var privateVariable = "I'm private";
var privateFunction = function() {}
return {
publicVariable: "I'm public",
publicMethod: function () {}
}
})();
The first version does not have private properties nor does it have a constructor, but it is faster and simpler. The second version is more complex, ugly, but has a constructor and private properties.
I'm not in a need for private properties, I just want to have a constructor. Is there something I am missing or are the two approaches above the only ones I've got?
function Singleton() {
if ( Singleton.instance )
return Singleton.instance;
Singleton.instance = this;
this.prop1 = 5;
this.method = function() {};
}​
Here is my solution with closures:
function Singleton() {
Singleton.getInstance = (function(_this) {
return function() { return _this; };
})(this);
}
Test:
var foo = new Singleton();
var bar = Singleton.getInstance();
foo === bar; // true
If you are just looking for a place to initialise your singleton, how about this?
var singleton = {
'pubvar': null,
'init': function() {
this.pubvar = 'I am public!';
return this;
}
}.init();
console.assert(singleton.pubvar === 'I am public!');
Simple and elegant.
var singleton = new function() { // <<----Notice the new here
//constructorcode....
this.publicproperty ="blabla";
}
This is basically the same as creating a function, then instantly assiging a new instace of it to the variable singleton. Like var singleton = new SingletonObject();
I highly advice against using singletons this way in javscript though because of the execution order is based on where in the file you place the object and not on your own logic.
What about this?
var Singleton = (function() {
var instance;
// this is actual constructor with params
return function(cfg) {
if (typeof instance == 'undefined') {
instance = this;
this.cfg = cfg;
}
return instance;
};
})();
var a = new Singleton('a');
var b = new Singleton('b');
//a === b; <-- true
//a.cfg <-- 'a'
//b.cfg <-- 'a'
I make it an actual Singleton with static functions and no this like so:
class S {
//"constructor"
static init() {
//Note: Since it's a singleton, there's no "this" instance.
//Instead, you store variables directly on the class.
S.myVar = 7;
}
static myOtherFunc() {
alert(S.myVar);
}
}
//Immediately call init() to make it the "constructor".
//Alternatively, you can call init() elsewhere if you'd
//like to initialize it at a particular time.
S.init();
//Later:
S.myOtherFunc();
S.myVar = 10;

Categories