Whats the equivalent of ES6 methods(class) in es5? - javascript

How would we polyfill es6 class methods into ES5?
I am reading a book and it says the following:
class Ninja {
constructor(name) {
this.name = name;
}
swingSword() {
return true;
}
}
is the same as
function Ninja(name) {
this.name = name;
}
Ninja.prototype.swingSword = function() {
return true;
};
I am just asking why are we adding the swingSword on the prototype and not inside the constructor function?
Because the function should be on the object and not on the prototype chain.
Am i right or wrong?

It should be on the prototype, methods are not per-instance data. Can't think of any language that implements it that way, the whole idea of classes is to have a whole class of objects that have the same set of methods.
If it was put it inside the constructor function, it would be a unique function per instance made with the constructor. e.g, 1000 objects == 1000 functions, per "method".

Adding the function to just the object would only work for a Ninja. To create a class that extends Ninja, for example Kunoichi, you would normally copy the Ninja prototype. Unfortunately, because swingSword is not in the prototype, your Kunoichi cannot swing swords.
You must add the function in prototype to allow the class to be extended.

If we add a method to the prototype, only one instance of that method exists in memory, and it’s shared between all objects created from the constructor.
If we add the swingSword method directly to the Ninja constructor function, then every object would have its own copy of that method, taking up more memory.

var $class = function ($superclass, config) {
// All classes have a superclass with the root
// of this $class hierarchy being Object.
var self = function (config) {
// Object.assign or $.extend or ...
config && Object.assign(this, config);
};
self.prototype = new $superclass(config);
return self;
};
var A = $class(Object, {
sayWhat: "Hello, I'm an A",
say: function () {
console.log(this.sayWhat);
}
});
var B = $class(A, {
sayWhat: "Hello, I'm a B"
});
var C = $class(B, {
say: function () {
console.log("C SAYS: " + this.sayWhat);
},
superSay: function () {
// how to call a superclass method
B.prototype.say.call(this);
}
});
var a = new A();
a.say();  // Hello, I'm an A
var b = new B();
b.say();  // Hello, I'm a B
var c = new C();
c.say();  // C SAYS: Hello, I'm a B
// create a "one-off" object
var d = new C({
sayWhat: "I'm special!",
say: function () {
console.log("hey!");
}
});
d.say();  // hey!
d.superSay();  // I'm special!
C.prototype.say.call(d);  // C SAYS: I'm special!

Related

TypeError: can't access property "constructor", object is undefined [duplicate]

What is the simplest/cleanest way to implement the singleton pattern in JavaScript?
I think the easiest way is to declare a simple object literal:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
If you want private members on your singleton instance, you can do something like this:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// All private members are accessible here
},
publicMethod2: function () {
}
};
})();
This has been called the module pattern, and it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.
If you want to prevent the modification of the singleton object, you can freeze it, using the ES5 Object.freeze method.
That will make the object immutable, preventing any modification to the its structure and values.
If you are using ES6, you can represent a singleton using ES Modules very easily, and you can even hold private state by declaring variables at the module scope:
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Then you can simply import the singleton object to use it:
import myInstance from './my-singleton.js'
// ...
I think the cleanest approach is something like:
var SingletonFactory = (function(){
function SingletonClass() {
//do stuff
}
var instance;
return {
getInstance: function(){
if (instance == null) {
instance = new SingletonClass();
// Hide the constructor so the returned object can't be new'd...
instance.constructor = null;
}
return instance;
}
};
})();
Afterwards, you can invoke the function as
var test = SingletonFactory.getInstance();
I'm not sure I agree with the module pattern being used as a replacement for a singleton pattern. I've often seen singletons used and abused in places where they're wholly unnecessary, and I'm sure the module pattern fills many gaps where programmers would otherwise use a singleton. However, the module pattern is not a singleton.
Module pattern:
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Everything initialized in the module pattern happens when Foo is declared. Additionally, the module pattern can be used to initialize a constructor, which could then be instantiated multiple times. While the module pattern is the right tool for many jobs, it's not equivalent to a singleton.
Singleton pattern:
short form
var Foo = function () {
"use strict";
if (Foo._instance) {
// This allows the constructor to be called multiple times
// and refer to the same instance. Another option is to
// throw an error.
return Foo._instance;
}
Foo._instance = this;
// Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
long form, using module pattern
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
// Instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
In both versions of the singleton pattern that I've provided, the constructor itself can be used as the accessor:
var a,
b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true
If you don't feel comfortable using the constructor this way, you can throw an error in the if (instance) statement, and stick to using the long form:
var a,
b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true
I should also mention that the singleton pattern fits well with the implicit constructor function pattern:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
// If the function wasn't called as a constructor,
// call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor
In ES6 the right way to do this is:
class MyClass {
constructor() {
if (MyClass._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error
Or, if you don't want an error to be thrown on the second instance creation, you can just return the last instance, like so:
class MyClass {
constructor() {
if (MyClass._instance) {
return MyClass._instance
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass()
var instanceTwo = new MyClass()
console.log(instanceOne === instanceTwo) // Logs "true"
In ECMAScript 2015 (ES6):
class Singleton {
constructor () {
if (!Singleton.instance) {
Singleton.instance = this
}
// Initialize object
return Singleton.instance
}
// Properties & Methods
}
const instance = new Singleton()
Object.freeze(instance)
export default instance
If you're using node.JS then you can take advantage of node.JS caching mechanism and your Singleton will be as simple as:
class Singleton {
constructor() {
this.message = 'I am an instance';
}
}
module.exports = new Singleton();
Please note that we export not the class Singleton but instance Singleton().
Node.JS will cache and reuse the same object each time it’s required.
For more details please check: Node.JS and Singleton Pattern
The following works in Node.js version 6:
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
We test:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
The simplest/cleanest for me means also simply to understand and no bells & whistles as are much discussed in the Java version of the discussion:
What is an efficient way to implement a singleton pattern in Java?
The answer that would fit simplest/cleanest best there from my point of view is:
Jonathan's answer to What is an efficient way to implement a singleton pattern in Java?
And it can only partly be translated to JavaScript. Some of the difference in JavaScript are:
constructors can't be private
Classes can't have declared fields
But given the latest ECMA syntax, it is possible to get close with:
Singleton pattern as a JavaScript class example
class Singleton {
constructor(field1,field2) {
this.field1=field1;
this.field2=field2;
Singleton.instance=this;
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance=new Singleton('DefaultField1','DefaultField2');
}
return Singleton.instance;
}
}
Example Usage
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Example Result
DefaultField1
DefaultField2
If you want to use classes:
class Singleton {
constructor(name, age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
}
let x = new Singleton('s', 1);
let y = new Singleton('k', 2);
Output for the above will be:
console.log(x.name, x.age, y.name, y.age) // s 1 s 1
Another way of writing Singleton using function
function AnotherSingleton (name,age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
let a = new AnotherSingleton('s', 1);
let b = new AnotherSingleton('k', 2);
Output for the above will be:
console.log(a.name, a.age, b.name, b.age) // s 1 s 1
There is more than one way to skin a cat :) Depending on your taste or specific need you can apply any of the proposed solutions. I personally go for Christian C. Salvadó's first solution whenever possible (when you don't need privacy).
Since the question was about the simplest and cleanest, that's the winner. Or even:
var myInstance = {}; // Done!
This (quote from my blog)...
var SingletonClass = new function() {
this.myFunction() {
// Do stuff
}
this.instance = 1;
}
doesn't make much sense (my blog example doesn't either) because it doesn't need any private variables, so it's pretty much the same as:
var SingletonClass = {
myFunction: function () {
// Do stuff
},
instance: 1
}
I deprecate my answer, see my other one.
Usually the module pattern (see Christian C. Salvadó's answer) which is not the singleton pattern is good enough. However, one of the features of the singleton is that its initialization is delayed till the object is needed. The module pattern lacks this feature.
My proposition (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Which compiled to this in JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Then I can do following:
window.iAmSingleton = singleton(function() {
/* This function should create and initialize singleton. */
alert("creating");
return {property1: 'value1', property2: 'value2'};
});
alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
I got this example from the *JavaScript Patterns
Build Better Applications with Coding and Design Patterns book (by Stoyan Stefanov). In case you need some simple implementation class like a singleton object, you can use an immediate function as in the following:
var ClassName;
(function() {
var instance;
ClassName = function ClassName() {
// If the private instance variable is already initialized, return a reference
if(instance) {
return instance;
}
// If the instance is not created, save a pointer of the original reference
// to the private instance variable.
instance = this;
// All constructor initialization will be here
// i.e.:
this.someProperty = 0;
this.someMethod = function() {
// Some action here
};
};
}());
And you can check this example by following test case:
// Extending defined class like singleton object using the new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
// Extending the defined class like a singleton object using the new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
// Testing makes these two objects point to the same instance
console.log(obj_1 === obj_2); // Result is true, and it points to the same instance object
// All prototype properties work
// no matter when they were defined
console.log(obj_1.nothing && obj_1.everything
&& obj_2.nothing && obj_2.everything); // Result true
// Values of properties which are defined inside of the constructor
console.log(obj_1.someProperty); // Outputs 0
console.log(obj_2.someProperty); // Outputs 0
// Changing property value
obj_1.someProperty = 1;
console.log(obj_1.someProperty); // Output 1
console.log(obj_2.someProperty); // Output 1
console.log(obj_1.constructor === ClassName); // Output true
This approach passes all test cases while a private static implementation will fail when a prototype extension is used (it can be fixed, but it will not be simple) and a public static implementation less advisable due to an instance is exposed to the public.
jsFiddly demo.
Short answer:
Because of the non-blocking nature of JavaScript, singletons in JavaScript are really ugly in use. Global variables will give you one instance through the whole application too without all these callbacks, and module pattern gently hides internals behind the interface. See Christian C. Salvadó's answer.
But, since you wanted a singleton…
var singleton = function(initializer) {
var state = 'initial';
var instance;
var queue = [];
var instanceReady = function(createdInstance) {
state = 'ready';
instance = createdInstance;
while (callback = queue.shift()) {
callback(instance);
}
};
return function(callback) {
if (state === 'initial') {
state = 'waiting';
queue.push(callback);
initializer(instanceReady);
} else if (state === 'waiting') {
queue.push(callback);
} else {
callback(instance);
}
};
};
Usage:
var singletonInitializer = function(instanceReady) {
var preparedObject = {property: 'value'};
// Calling instanceReady notifies the singleton that the instance is ready to use
instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// Get the instance and use it
s(function(instance) {
instance.doSomething();
});
Explanation:
Singletons give you more than just one instance through the whole application: their initialization is delayed till the first use. This is really a big thing when you deal with objects whose initialization is expensive. Expensive usually means I/O and in JavaScript I/O always mean callbacks.
Don't trust answers which give you interface like instance = singleton.getInstance(), they all miss the point.
If they don't take a callback to be run when an instance is ready, then they won't work when the initializer does I/O.
Yeah, callbacks always look uglier than a function call which immediately returns an object instance. But again: when you do I/O, callbacks are obligatory. If you don't want to do any I/O, then instantiation is cheap enough to do it at program start.
Example 1, cheap initializer:
var simpleInitializer = function(instanceReady) {
console.log("Initializer started");
instanceReady({property: "initial value"});
}
var simple = singleton(simpleInitializer);
console.log("Tests started. Singleton instance should not be initalized yet.");
simple(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
simple(function(inst) {
console.log("Access 2");
console.log("Current property value: " + inst.property);
});
Example 2, initialization with I/O:
In this example, setTimeout fakes some expensive I/O operation. This illustrates why singletons in JavaScript really need callbacks.
var heavyInitializer = function(instanceReady) {
console.log("Initializer started");
var onTimeout = function() {
console.log("Initializer did his heavy work");
instanceReady({property: "initial value"});
};
setTimeout(onTimeout, 500);
};
var heavy = singleton(heavyInitializer);
console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");
heavy(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
heavy(function(inst) {
console.log("Access 2. You can see callbacks order is preserved.");
console.log("Current property value: " + inst.property);
});
console.log("We made it to the end of the file. Instance is not ready yet.");
Christian C. Salvadó's and zzzzBov's answer have both given wonderful answers, but just to add my own interpretation based on my having moved into heavy Node.js development from PHP/Zend Framework where singleton patterns were common.
The following, comment-documented code is based on the following requirements:
one and only one instance of the function object may be instantiated
the instance is not publicly available and may only be accessed through a public method
the constructor is not publicly available and may only be instantiated if there is not already an instance available
the declaration of the constructor must allow its prototype chain to be modified. This will allow the constructor to inherit from other prototypes, and offer "public" methods for the instance
My code is very similar to zzzzBov's answer except I've added a prototype chain to the constructor and more comments that should help those coming from PHP or a similar language translate traditional OOP to JavaScript's prototypical nature. It may not be the "simplest" but I believe it is the most proper.
// Declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
"use strict";
// 'instance' and 'constructor' should not be available in a "public" scope
// here they are "private", thus available only within
// the scope of the self-executing anonymous function
var _instance=null;
var _constructor = function (name) {
this.name = name || 'default';
}
// Prototypes will be "public" methods available from the instance
_constructor.prototype.getName = function () {
return this.name;
}
// Using the module pattern, return a static object
// which essentially is a list of "public static" methods
return {
// Because getInstance is defined within the same scope
// it can access the "private" 'instance' and 'constructor' vars
getInstance:function (name) {
if (!_instance) {
console.log('creating'); // This should only happen once
_instance = new _constructor(name);
}
console.log('returning');
return _instance;
}
}
})(); // Self execute
// Ensure 'instance' and 'constructor' are unavailable
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined
// Assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
// Ensure 'a' and 'b' are truly equal
console.log(a === b); // true
console.log(a.getName()); // "first"
console.log(b.getName()); // Also returns "first" because it's the same instance as 'a'
Note that technically, the self-executing anonymous function is itself a singleton as demonstrated nicely in the code provided by Christian C. Salvadó. The only catch here is that it is not possible to modify the prototype chain of the constructor when the constructor itself is anonymous.
Keep in mind that to JavaScript, the concepts of “public” and “private” do not apply as they do in PHP or Java. But we have achieved the same effect by leveraging JavaScript’s rules of functional scope availability.
You could just do:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// Whatever
}
})()
I think I have found the cleanest way to program in JavaScript, but you'll need some imagination. I got this idea from a working technique in the book JavaScript: The Good Parts.
Instead of using the new keyword, you could create a class like this:
function Class()
{
var obj = {}; // Could also be used for inheritance if you don't start with an empty object.
var privateVar;
obj.publicVar;
obj.publicMethod = publicMethod;
function publicMethod(){}
function privateMethod(){}
return obj;
}
You can instantiate the above object by saying:
var objInst = Class(); // !!! NO NEW KEYWORD
Now with this work method in mind, you could create a singleton like this:
ClassSingleton = function()
{
var instance = null;
function Class() // This is the class like the above one
{
var obj = {};
return obj;
}
function getInstance()
{
if( !instance )
instance = Class(); // Again no 'new' keyword;
return instance;
}
return { getInstance : getInstance };
}();
Now you can get your instance by calling
var obj = ClassSingleton.getInstance();
I think this is the neatest way as the complete "Class" is not even accessible.
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 = "I'm 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;
}
};
})();
For me the cleanest way to do so is:
const singleton = new class {
name = "foo"
constructor() {
console.log(`Singleton ${this.name} constructed`)
}
}
With this syntax you are certain your singleton is and will remain unique. You can also enjoy the sugarness of class syntax and use this as expected.
(Note that class fields require node v12+ or a modern browser.)
This is how I implement singleton pattern using ES6 features. Yes, I know this does not look like an Object-oriented approach, but I find this method is easy to implement and a clean way to implement.
const Singleton = (() => {
var _instance = !_instance && new Object('Object created....');
return () => _instance;
})();
//************************************************************************
var instance1 = Singleton();
var instance2 = Singleton();
console.log(instance1 === instance2); // true
This should work:
function Klass() {
var instance = this;
Klass = function () { return instance; }
}
I believe this is the simplest/cleanest and most intuitive way though it requires ECMAScript 2016 (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
I've found the following to be the easiest singleton pattern, because using the new operator makes this immediately available within the function, eliminating the need to return an object literal:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Using ES6 classes and private static fields. Invoking new instances of the Singleton class will return the same instance. The instance variable is also private and can't be accessed outside the class.
class Singleton {
// # is a new Javascript feature that denotes private
static #instance;
constructor() {
if (!Singleton.#instance) {
Singleton.#instance = this
}
return Singleton.#instance
}
get() {
return Singleton.#instance;
}
}
const a = new Singleton();
const b = new Singleton();
console.log(a.get() === b.get()) // true
console.log(Singleton.instance === undefined) // true
function Once() {
return this.constructor.instance || (this.constructor.instance = this);
}
function Application(name) {
let app = Once.call(this);
app.name = name;
return app;
}
If you are into classes:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Test:
console.log(new Once() === new Once());
let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');
console.log(app1 === app2);
console.log(app1.name); // Barfoo
Following is the snippet from my walkthrough to implement a singleton pattern. This occurred to me during an interview process and I felt that I should capture this somewhere.
/*************************************************
* SINGLETON PATTERN IMPLEMENTATION *
*************************************************/
// Since there aren't any classes in JavaScript, every object
// is technically a singleton if you don't inherit from it
// or copy from it.
var single = {};
// Singleton Implementations
//
// Declaring as a global object...you are being judged!
var Logger = function() {
// global_log is/will be defined in the GLOBAL scope here
if(typeof global_log === 'undefined'){
global_log = this;
}
return global_log;
};
// The below 'fix' solves the GLOABL variable problem, but
// the log_instance is publicly available and thus can be
// tampered with.
function Logger() {
if(typeof Logger.log_instance === 'undefined') {
Logger.log_instance = this;
}
return Logger.log_instance;
};
// The correct way to do it to give it a closure!
function logFactory() {
var log_instance; // Private instance
var _initLog = function() { // Private init method
log_instance = 'initialized';
console.log("logger initialized!")
}
return {
getLog : function(){ // The 'privileged' method
if(typeof log_instance === 'undefined') {
_initLog();
}
return log_instance;
}
};
}
/***** TEST CODE ************************************************
// Using the Logger singleton
var logger = logFactory(); // Did I just give LogFactory a closure?
// Create an instance of the logger
var a = logger.getLog();
// Do some work
// Get another instance of the logger
var b = logger.getLog();
// Check if the two logger instances are same
console.log(a === b); // true
*******************************************************************/
The same can be found on my gist page.
My two cents: I have a constructor function (CF), for example,
var A = function(arg1){
this.arg1 = arg1
};
I need just every object created by this CF to be the same.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
Test
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
Singleton:
Ensure a class has only one instance and provides a global point of access to it.
The singleton pattern limits the number of instances of a particular object to just one. This single instance is called the singleton.
defines getInstance() which returns the unique instance.
responsible for creating and managing the instance object.
The singleton object is implemented as an immediate anonymous function. The function executes immediately by wrapping it in brackets followed by two additional brackets. It is called anonymous because it doesn't have a name.
Sample Program
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
run()
Here is a simple example to explain the singleton pattern in JavaScript.
var Singleton = (function() {
var instance;
var init = function() {
return {
display:function() {
alert("This is a singleton pattern demo");
}
};
};
return {
getInstance:function(){
if(!instance){
alert("Singleton check");
instance = init();
}
return instance;
}
};
})();
// In this call first display alert("Singleton check")
// and then alert("This is a singleton pattern demo");
// It means one object is created
var inst = Singleton.getInstance();
inst.display();
// In this call only display alert("This is a singleton pattern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1 = Singleton.getInstance();
inst1.display();
let MySingleton = (function () {
var _instance
function init() {
if(!_instance) {
_instance = { $knew: 1 }
}
return _instance
}
let publicAPIs = {
getInstance: function() {
return init()
}
}
// this prevents customize the MySingleton, like MySingleton.x = 1
Object.freeze(publicAPIs)
// this prevents customize the MySingleton.getInstance(), like MySingleton.getInstance().x = 1
Object.freeze(publicAPIs.getInstance())
return publicAPIs
})();
I needed several singletons with:
lazy initialisation
initial parameters
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 the 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 in order for window[] to work, but with some simple typechecking, window.name and window.construct are also possible.

Create a singleton with unique instance in Javascript [duplicate]

What is the simplest/cleanest way to implement the singleton pattern in JavaScript?
I think the easiest way is to declare a simple object literal:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
If you want private members on your singleton instance, you can do something like this:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// All private members are accessible here
},
publicMethod2: function () {
}
};
})();
This has been called the module pattern, and it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.
If you want to prevent the modification of the singleton object, you can freeze it, using the ES5 Object.freeze method.
That will make the object immutable, preventing any modification to the its structure and values.
If you are using ES6, you can represent a singleton using ES Modules very easily, and you can even hold private state by declaring variables at the module scope:
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Then you can simply import the singleton object to use it:
import myInstance from './my-singleton.js'
// ...
I think the cleanest approach is something like:
var SingletonFactory = (function(){
function SingletonClass() {
//do stuff
}
var instance;
return {
getInstance: function(){
if (instance == null) {
instance = new SingletonClass();
// Hide the constructor so the returned object can't be new'd...
instance.constructor = null;
}
return instance;
}
};
})();
Afterwards, you can invoke the function as
var test = SingletonFactory.getInstance();
I'm not sure I agree with the module pattern being used as a replacement for a singleton pattern. I've often seen singletons used and abused in places where they're wholly unnecessary, and I'm sure the module pattern fills many gaps where programmers would otherwise use a singleton. However, the module pattern is not a singleton.
Module pattern:
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Everything initialized in the module pattern happens when Foo is declared. Additionally, the module pattern can be used to initialize a constructor, which could then be instantiated multiple times. While the module pattern is the right tool for many jobs, it's not equivalent to a singleton.
Singleton pattern:
short form
var Foo = function () {
"use strict";
if (Foo._instance) {
// This allows the constructor to be called multiple times
// and refer to the same instance. Another option is to
// throw an error.
return Foo._instance;
}
Foo._instance = this;
// Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
long form, using module pattern
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
// Instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
In both versions of the singleton pattern that I've provided, the constructor itself can be used as the accessor:
var a,
b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true
If you don't feel comfortable using the constructor this way, you can throw an error in the if (instance) statement, and stick to using the long form:
var a,
b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true
I should also mention that the singleton pattern fits well with the implicit constructor function pattern:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
// If the function wasn't called as a constructor,
// call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor
In ES6 the right way to do this is:
class MyClass {
constructor() {
if (MyClass._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error
Or, if you don't want an error to be thrown on the second instance creation, you can just return the last instance, like so:
class MyClass {
constructor() {
if (MyClass._instance) {
return MyClass._instance
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass()
var instanceTwo = new MyClass()
console.log(instanceOne === instanceTwo) // Logs "true"
In ECMAScript 2015 (ES6):
class Singleton {
constructor () {
if (!Singleton.instance) {
Singleton.instance = this
}
// Initialize object
return Singleton.instance
}
// Properties & Methods
}
const instance = new Singleton()
Object.freeze(instance)
export default instance
If you're using node.JS then you can take advantage of node.JS caching mechanism and your Singleton will be as simple as:
class Singleton {
constructor() {
this.message = 'I am an instance';
}
}
module.exports = new Singleton();
Please note that we export not the class Singleton but instance Singleton().
Node.JS will cache and reuse the same object each time it’s required.
For more details please check: Node.JS and Singleton Pattern
The following works in Node.js version 6:
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
We test:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
The simplest/cleanest for me means also simply to understand and no bells & whistles as are much discussed in the Java version of the discussion:
What is an efficient way to implement a singleton pattern in Java?
The answer that would fit simplest/cleanest best there from my point of view is:
Jonathan's answer to What is an efficient way to implement a singleton pattern in Java?
And it can only partly be translated to JavaScript. Some of the difference in JavaScript are:
constructors can't be private
Classes can't have declared fields
But given the latest ECMA syntax, it is possible to get close with:
Singleton pattern as a JavaScript class example
class Singleton {
constructor(field1,field2) {
this.field1=field1;
this.field2=field2;
Singleton.instance=this;
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance=new Singleton('DefaultField1','DefaultField2');
}
return Singleton.instance;
}
}
Example Usage
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Example Result
DefaultField1
DefaultField2
If you want to use classes:
class Singleton {
constructor(name, age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
}
let x = new Singleton('s', 1);
let y = new Singleton('k', 2);
Output for the above will be:
console.log(x.name, x.age, y.name, y.age) // s 1 s 1
Another way of writing Singleton using function
function AnotherSingleton (name,age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
let a = new AnotherSingleton('s', 1);
let b = new AnotherSingleton('k', 2);
Output for the above will be:
console.log(a.name, a.age, b.name, b.age) // s 1 s 1
There is more than one way to skin a cat :) Depending on your taste or specific need you can apply any of the proposed solutions. I personally go for Christian C. Salvadó's first solution whenever possible (when you don't need privacy).
Since the question was about the simplest and cleanest, that's the winner. Or even:
var myInstance = {}; // Done!
This (quote from my blog)...
var SingletonClass = new function() {
this.myFunction() {
// Do stuff
}
this.instance = 1;
}
doesn't make much sense (my blog example doesn't either) because it doesn't need any private variables, so it's pretty much the same as:
var SingletonClass = {
myFunction: function () {
// Do stuff
},
instance: 1
}
I deprecate my answer, see my other one.
Usually the module pattern (see Christian C. Salvadó's answer) which is not the singleton pattern is good enough. However, one of the features of the singleton is that its initialization is delayed till the object is needed. The module pattern lacks this feature.
My proposition (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Which compiled to this in JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Then I can do following:
window.iAmSingleton = singleton(function() {
/* This function should create and initialize singleton. */
alert("creating");
return {property1: 'value1', property2: 'value2'};
});
alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
I got this example from the *JavaScript Patterns
Build Better Applications with Coding and Design Patterns book (by Stoyan Stefanov). In case you need some simple implementation class like a singleton object, you can use an immediate function as in the following:
var ClassName;
(function() {
var instance;
ClassName = function ClassName() {
// If the private instance variable is already initialized, return a reference
if(instance) {
return instance;
}
// If the instance is not created, save a pointer of the original reference
// to the private instance variable.
instance = this;
// All constructor initialization will be here
// i.e.:
this.someProperty = 0;
this.someMethod = function() {
// Some action here
};
};
}());
And you can check this example by following test case:
// Extending defined class like singleton object using the new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
// Extending the defined class like a singleton object using the new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
// Testing makes these two objects point to the same instance
console.log(obj_1 === obj_2); // Result is true, and it points to the same instance object
// All prototype properties work
// no matter when they were defined
console.log(obj_1.nothing && obj_1.everything
&& obj_2.nothing && obj_2.everything); // Result true
// Values of properties which are defined inside of the constructor
console.log(obj_1.someProperty); // Outputs 0
console.log(obj_2.someProperty); // Outputs 0
// Changing property value
obj_1.someProperty = 1;
console.log(obj_1.someProperty); // Output 1
console.log(obj_2.someProperty); // Output 1
console.log(obj_1.constructor === ClassName); // Output true
This approach passes all test cases while a private static implementation will fail when a prototype extension is used (it can be fixed, but it will not be simple) and a public static implementation less advisable due to an instance is exposed to the public.
jsFiddly demo.
Short answer:
Because of the non-blocking nature of JavaScript, singletons in JavaScript are really ugly in use. Global variables will give you one instance through the whole application too without all these callbacks, and module pattern gently hides internals behind the interface. See Christian C. Salvadó's answer.
But, since you wanted a singleton…
var singleton = function(initializer) {
var state = 'initial';
var instance;
var queue = [];
var instanceReady = function(createdInstance) {
state = 'ready';
instance = createdInstance;
while (callback = queue.shift()) {
callback(instance);
}
};
return function(callback) {
if (state === 'initial') {
state = 'waiting';
queue.push(callback);
initializer(instanceReady);
} else if (state === 'waiting') {
queue.push(callback);
} else {
callback(instance);
}
};
};
Usage:
var singletonInitializer = function(instanceReady) {
var preparedObject = {property: 'value'};
// Calling instanceReady notifies the singleton that the instance is ready to use
instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// Get the instance and use it
s(function(instance) {
instance.doSomething();
});
Explanation:
Singletons give you more than just one instance through the whole application: their initialization is delayed till the first use. This is really a big thing when you deal with objects whose initialization is expensive. Expensive usually means I/O and in JavaScript I/O always mean callbacks.
Don't trust answers which give you interface like instance = singleton.getInstance(), they all miss the point.
If they don't take a callback to be run when an instance is ready, then they won't work when the initializer does I/O.
Yeah, callbacks always look uglier than a function call which immediately returns an object instance. But again: when you do I/O, callbacks are obligatory. If you don't want to do any I/O, then instantiation is cheap enough to do it at program start.
Example 1, cheap initializer:
var simpleInitializer = function(instanceReady) {
console.log("Initializer started");
instanceReady({property: "initial value"});
}
var simple = singleton(simpleInitializer);
console.log("Tests started. Singleton instance should not be initalized yet.");
simple(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
simple(function(inst) {
console.log("Access 2");
console.log("Current property value: " + inst.property);
});
Example 2, initialization with I/O:
In this example, setTimeout fakes some expensive I/O operation. This illustrates why singletons in JavaScript really need callbacks.
var heavyInitializer = function(instanceReady) {
console.log("Initializer started");
var onTimeout = function() {
console.log("Initializer did his heavy work");
instanceReady({property: "initial value"});
};
setTimeout(onTimeout, 500);
};
var heavy = singleton(heavyInitializer);
console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");
heavy(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
heavy(function(inst) {
console.log("Access 2. You can see callbacks order is preserved.");
console.log("Current property value: " + inst.property);
});
console.log("We made it to the end of the file. Instance is not ready yet.");
Christian C. Salvadó's and zzzzBov's answer have both given wonderful answers, but just to add my own interpretation based on my having moved into heavy Node.js development from PHP/Zend Framework where singleton patterns were common.
The following, comment-documented code is based on the following requirements:
one and only one instance of the function object may be instantiated
the instance is not publicly available and may only be accessed through a public method
the constructor is not publicly available and may only be instantiated if there is not already an instance available
the declaration of the constructor must allow its prototype chain to be modified. This will allow the constructor to inherit from other prototypes, and offer "public" methods for the instance
My code is very similar to zzzzBov's answer except I've added a prototype chain to the constructor and more comments that should help those coming from PHP or a similar language translate traditional OOP to JavaScript's prototypical nature. It may not be the "simplest" but I believe it is the most proper.
// Declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
"use strict";
// 'instance' and 'constructor' should not be available in a "public" scope
// here they are "private", thus available only within
// the scope of the self-executing anonymous function
var _instance=null;
var _constructor = function (name) {
this.name = name || 'default';
}
// Prototypes will be "public" methods available from the instance
_constructor.prototype.getName = function () {
return this.name;
}
// Using the module pattern, return a static object
// which essentially is a list of "public static" methods
return {
// Because getInstance is defined within the same scope
// it can access the "private" 'instance' and 'constructor' vars
getInstance:function (name) {
if (!_instance) {
console.log('creating'); // This should only happen once
_instance = new _constructor(name);
}
console.log('returning');
return _instance;
}
}
})(); // Self execute
// Ensure 'instance' and 'constructor' are unavailable
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined
// Assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
// Ensure 'a' and 'b' are truly equal
console.log(a === b); // true
console.log(a.getName()); // "first"
console.log(b.getName()); // Also returns "first" because it's the same instance as 'a'
Note that technically, the self-executing anonymous function is itself a singleton as demonstrated nicely in the code provided by Christian C. Salvadó. The only catch here is that it is not possible to modify the prototype chain of the constructor when the constructor itself is anonymous.
Keep in mind that to JavaScript, the concepts of “public” and “private” do not apply as they do in PHP or Java. But we have achieved the same effect by leveraging JavaScript’s rules of functional scope availability.
You could just do:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// Whatever
}
})()
I think I have found the cleanest way to program in JavaScript, but you'll need some imagination. I got this idea from a working technique in the book JavaScript: The Good Parts.
Instead of using the new keyword, you could create a class like this:
function Class()
{
var obj = {}; // Could also be used for inheritance if you don't start with an empty object.
var privateVar;
obj.publicVar;
obj.publicMethod = publicMethod;
function publicMethod(){}
function privateMethod(){}
return obj;
}
You can instantiate the above object by saying:
var objInst = Class(); // !!! NO NEW KEYWORD
Now with this work method in mind, you could create a singleton like this:
ClassSingleton = function()
{
var instance = null;
function Class() // This is the class like the above one
{
var obj = {};
return obj;
}
function getInstance()
{
if( !instance )
instance = Class(); // Again no 'new' keyword;
return instance;
}
return { getInstance : getInstance };
}();
Now you can get your instance by calling
var obj = ClassSingleton.getInstance();
I think this is the neatest way as the complete "Class" is not even accessible.
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 = "I'm 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;
}
};
})();
For me the cleanest way to do so is:
const singleton = new class {
name = "foo"
constructor() {
console.log(`Singleton ${this.name} constructed`)
}
}
With this syntax you are certain your singleton is and will remain unique. You can also enjoy the sugarness of class syntax and use this as expected.
(Note that class fields require node v12+ or a modern browser.)
This is how I implement singleton pattern using ES6 features. Yes, I know this does not look like an Object-oriented approach, but I find this method is easy to implement and a clean way to implement.
const Singleton = (() => {
var _instance = !_instance && new Object('Object created....');
return () => _instance;
})();
//************************************************************************
var instance1 = Singleton();
var instance2 = Singleton();
console.log(instance1 === instance2); // true
This should work:
function Klass() {
var instance = this;
Klass = function () { return instance; }
}
I believe this is the simplest/cleanest and most intuitive way though it requires ECMAScript 2016 (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
I've found the following to be the easiest singleton pattern, because using the new operator makes this immediately available within the function, eliminating the need to return an object literal:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Using ES6 classes and private static fields. Invoking new instances of the Singleton class will return the same instance. The instance variable is also private and can't be accessed outside the class.
class Singleton {
// # is a new Javascript feature that denotes private
static #instance;
constructor() {
if (!Singleton.#instance) {
Singleton.#instance = this
}
return Singleton.#instance
}
get() {
return Singleton.#instance;
}
}
const a = new Singleton();
const b = new Singleton();
console.log(a.get() === b.get()) // true
console.log(Singleton.instance === undefined) // true
function Once() {
return this.constructor.instance || (this.constructor.instance = this);
}
function Application(name) {
let app = Once.call(this);
app.name = name;
return app;
}
If you are into classes:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Test:
console.log(new Once() === new Once());
let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');
console.log(app1 === app2);
console.log(app1.name); // Barfoo
Following is the snippet from my walkthrough to implement a singleton pattern. This occurred to me during an interview process and I felt that I should capture this somewhere.
/*************************************************
* SINGLETON PATTERN IMPLEMENTATION *
*************************************************/
// Since there aren't any classes in JavaScript, every object
// is technically a singleton if you don't inherit from it
// or copy from it.
var single = {};
// Singleton Implementations
//
// Declaring as a global object...you are being judged!
var Logger = function() {
// global_log is/will be defined in the GLOBAL scope here
if(typeof global_log === 'undefined'){
global_log = this;
}
return global_log;
};
// The below 'fix' solves the GLOABL variable problem, but
// the log_instance is publicly available and thus can be
// tampered with.
function Logger() {
if(typeof Logger.log_instance === 'undefined') {
Logger.log_instance = this;
}
return Logger.log_instance;
};
// The correct way to do it to give it a closure!
function logFactory() {
var log_instance; // Private instance
var _initLog = function() { // Private init method
log_instance = 'initialized';
console.log("logger initialized!")
}
return {
getLog : function(){ // The 'privileged' method
if(typeof log_instance === 'undefined') {
_initLog();
}
return log_instance;
}
};
}
/***** TEST CODE ************************************************
// Using the Logger singleton
var logger = logFactory(); // Did I just give LogFactory a closure?
// Create an instance of the logger
var a = logger.getLog();
// Do some work
// Get another instance of the logger
var b = logger.getLog();
// Check if the two logger instances are same
console.log(a === b); // true
*******************************************************************/
The same can be found on my gist page.
My two cents: I have a constructor function (CF), for example,
var A = function(arg1){
this.arg1 = arg1
};
I need just every object created by this CF to be the same.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
Test
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
Singleton:
Ensure a class has only one instance and provides a global point of access to it.
The singleton pattern limits the number of instances of a particular object to just one. This single instance is called the singleton.
defines getInstance() which returns the unique instance.
responsible for creating and managing the instance object.
The singleton object is implemented as an immediate anonymous function. The function executes immediately by wrapping it in brackets followed by two additional brackets. It is called anonymous because it doesn't have a name.
Sample Program
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
run()
Here is a simple example to explain the singleton pattern in JavaScript.
var Singleton = (function() {
var instance;
var init = function() {
return {
display:function() {
alert("This is a singleton pattern demo");
}
};
};
return {
getInstance:function(){
if(!instance){
alert("Singleton check");
instance = init();
}
return instance;
}
};
})();
// In this call first display alert("Singleton check")
// and then alert("This is a singleton pattern demo");
// It means one object is created
var inst = Singleton.getInstance();
inst.display();
// In this call only display alert("This is a singleton pattern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1 = Singleton.getInstance();
inst1.display();
let MySingleton = (function () {
var _instance
function init() {
if(!_instance) {
_instance = { $knew: 1 }
}
return _instance
}
let publicAPIs = {
getInstance: function() {
return init()
}
}
// this prevents customize the MySingleton, like MySingleton.x = 1
Object.freeze(publicAPIs)
// this prevents customize the MySingleton.getInstance(), like MySingleton.getInstance().x = 1
Object.freeze(publicAPIs.getInstance())
return publicAPIs
})();
I needed several singletons with:
lazy initialisation
initial parameters
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 the 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 in order for window[] to work, but with some simple typechecking, window.name and window.construct are also possible.

How to create singleton class and where we should use singleton class in Javascript? [duplicate]

What is the simplest/cleanest way to implement the singleton pattern in JavaScript?
I think the easiest way is to declare a simple object literal:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
If you want private members on your singleton instance, you can do something like this:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// All private members are accessible here
},
publicMethod2: function () {
}
};
})();
This has been called the module pattern, and it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.
If you want to prevent the modification of the singleton object, you can freeze it, using the ES5 Object.freeze method.
That will make the object immutable, preventing any modification to the its structure and values.
If you are using ES6, you can represent a singleton using ES Modules very easily, and you can even hold private state by declaring variables at the module scope:
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
Then you can simply import the singleton object to use it:
import myInstance from './my-singleton.js'
// ...
I think the cleanest approach is something like:
var SingletonFactory = (function(){
function SingletonClass() {
//do stuff
}
var instance;
return {
getInstance: function(){
if (instance == null) {
instance = new SingletonClass();
// Hide the constructor so the returned object can't be new'd...
instance.constructor = null;
}
return instance;
}
};
})();
Afterwards, you can invoke the function as
var test = SingletonFactory.getInstance();
I'm not sure I agree with the module pattern being used as a replacement for a singleton pattern. I've often seen singletons used and abused in places where they're wholly unnecessary, and I'm sure the module pattern fills many gaps where programmers would otherwise use a singleton. However, the module pattern is not a singleton.
Module pattern:
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
Everything initialized in the module pattern happens when Foo is declared. Additionally, the module pattern can be used to initialize a constructor, which could then be instantiated multiple times. While the module pattern is the right tool for many jobs, it's not equivalent to a singleton.
Singleton pattern:
short form
var Foo = function () {
"use strict";
if (Foo._instance) {
// This allows the constructor to be called multiple times
// and refer to the same instance. Another option is to
// throw an error.
return Foo._instance;
}
Foo._instance = this;
// Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
long form, using module pattern
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
// Instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
In both versions of the singleton pattern that I've provided, the constructor itself can be used as the accessor:
var a,
b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true
If you don't feel comfortable using the constructor this way, you can throw an error in the if (instance) statement, and stick to using the long form:
var a,
b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true
I should also mention that the singleton pattern fits well with the implicit constructor function pattern:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
// If the function wasn't called as a constructor,
// call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor
In ES6 the right way to do this is:
class MyClass {
constructor() {
if (MyClass._instance) {
throw new Error("Singleton classes can't be instantiated more than once.")
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error
Or, if you don't want an error to be thrown on the second instance creation, you can just return the last instance, like so:
class MyClass {
constructor() {
if (MyClass._instance) {
return MyClass._instance
}
MyClass._instance = this;
// ... Your rest of the constructor code goes after this
}
}
var instanceOne = new MyClass()
var instanceTwo = new MyClass()
console.log(instanceOne === instanceTwo) // Logs "true"
In ECMAScript 2015 (ES6):
class Singleton {
constructor () {
if (!Singleton.instance) {
Singleton.instance = this
}
// Initialize object
return Singleton.instance
}
// Properties & Methods
}
const instance = new Singleton()
Object.freeze(instance)
export default instance
If you're using node.JS then you can take advantage of node.JS caching mechanism and your Singleton will be as simple as:
class Singleton {
constructor() {
this.message = 'I am an instance';
}
}
module.exports = new Singleton();
Please note that we export not the class Singleton but instance Singleton().
Node.JS will cache and reuse the same object each time it’s required.
For more details please check: Node.JS and Singleton Pattern
The following works in Node.js version 6:
class Foo {
constructor(msg) {
if (Foo.singleton) {
return Foo.singleton;
}
this.msg = msg;
Foo.singleton = this;
return Foo.singleton;
}
}
We test:
const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
The simplest/cleanest for me means also simply to understand and no bells & whistles as are much discussed in the Java version of the discussion:
What is an efficient way to implement a singleton pattern in Java?
The answer that would fit simplest/cleanest best there from my point of view is:
Jonathan's answer to What is an efficient way to implement a singleton pattern in Java?
And it can only partly be translated to JavaScript. Some of the difference in JavaScript are:
constructors can't be private
Classes can't have declared fields
But given the latest ECMA syntax, it is possible to get close with:
Singleton pattern as a JavaScript class example
class Singleton {
constructor(field1,field2) {
this.field1=field1;
this.field2=field2;
Singleton.instance=this;
}
static getInstance() {
if (!Singleton.instance) {
Singleton.instance=new Singleton('DefaultField1','DefaultField2');
}
return Singleton.instance;
}
}
Example Usage
console.log(Singleton.getInstance().field1);
console.log(Singleton.getInstance().field2);
Example Result
DefaultField1
DefaultField2
If you want to use classes:
class Singleton {
constructor(name, age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
}
let x = new Singleton('s', 1);
let y = new Singleton('k', 2);
Output for the above will be:
console.log(x.name, x.age, y.name, y.age) // s 1 s 1
Another way of writing Singleton using function
function AnotherSingleton (name,age) {
this.name = name;
this.age = age;
if(this.constructor.instance)
return this.constructor.instance;
this.constructor.instance = this;
}
let a = new AnotherSingleton('s', 1);
let b = new AnotherSingleton('k', 2);
Output for the above will be:
console.log(a.name, a.age, b.name, b.age) // s 1 s 1
There is more than one way to skin a cat :) Depending on your taste or specific need you can apply any of the proposed solutions. I personally go for Christian C. Salvadó's first solution whenever possible (when you don't need privacy).
Since the question was about the simplest and cleanest, that's the winner. Or even:
var myInstance = {}; // Done!
This (quote from my blog)...
var SingletonClass = new function() {
this.myFunction() {
// Do stuff
}
this.instance = 1;
}
doesn't make much sense (my blog example doesn't either) because it doesn't need any private variables, so it's pretty much the same as:
var SingletonClass = {
myFunction: function () {
// Do stuff
},
instance: 1
}
I deprecate my answer, see my other one.
Usually the module pattern (see Christian C. Salvadó's answer) which is not the singleton pattern is good enough. However, one of the features of the singleton is that its initialization is delayed till the object is needed. The module pattern lacks this feature.
My proposition (CoffeeScript):
window.singleton = (initializer) ->
instance = undefined
() ->
return instance unless instance is undefined
instance = initializer()
Which compiled to this in JavaScript:
window.singleton = function(initializer) {
var instance;
instance = void 0;
return function() {
if (instance !== void 0) {
return instance;
}
return instance = initializer();
};
};
Then I can do following:
window.iAmSingleton = singleton(function() {
/* This function should create and initialize singleton. */
alert("creating");
return {property1: 'value1', property2: 'value2'};
});
alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
I got this example from the *JavaScript Patterns
Build Better Applications with Coding and Design Patterns book (by Stoyan Stefanov). In case you need some simple implementation class like a singleton object, you can use an immediate function as in the following:
var ClassName;
(function() {
var instance;
ClassName = function ClassName() {
// If the private instance variable is already initialized, return a reference
if(instance) {
return instance;
}
// If the instance is not created, save a pointer of the original reference
// to the private instance variable.
instance = this;
// All constructor initialization will be here
// i.e.:
this.someProperty = 0;
this.someMethod = function() {
// Some action here
};
};
}());
And you can check this example by following test case:
// Extending defined class like singleton object using the new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
// Extending the defined class like a singleton object using the new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
// Testing makes these two objects point to the same instance
console.log(obj_1 === obj_2); // Result is true, and it points to the same instance object
// All prototype properties work
// no matter when they were defined
console.log(obj_1.nothing && obj_1.everything
&& obj_2.nothing && obj_2.everything); // Result true
// Values of properties which are defined inside of the constructor
console.log(obj_1.someProperty); // Outputs 0
console.log(obj_2.someProperty); // Outputs 0
// Changing property value
obj_1.someProperty = 1;
console.log(obj_1.someProperty); // Output 1
console.log(obj_2.someProperty); // Output 1
console.log(obj_1.constructor === ClassName); // Output true
This approach passes all test cases while a private static implementation will fail when a prototype extension is used (it can be fixed, but it will not be simple) and a public static implementation less advisable due to an instance is exposed to the public.
jsFiddly demo.
Short answer:
Because of the non-blocking nature of JavaScript, singletons in JavaScript are really ugly in use. Global variables will give you one instance through the whole application too without all these callbacks, and module pattern gently hides internals behind the interface. See Christian C. Salvadó's answer.
But, since you wanted a singleton…
var singleton = function(initializer) {
var state = 'initial';
var instance;
var queue = [];
var instanceReady = function(createdInstance) {
state = 'ready';
instance = createdInstance;
while (callback = queue.shift()) {
callback(instance);
}
};
return function(callback) {
if (state === 'initial') {
state = 'waiting';
queue.push(callback);
initializer(instanceReady);
} else if (state === 'waiting') {
queue.push(callback);
} else {
callback(instance);
}
};
};
Usage:
var singletonInitializer = function(instanceReady) {
var preparedObject = {property: 'value'};
// Calling instanceReady notifies the singleton that the instance is ready to use
instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// Get the instance and use it
s(function(instance) {
instance.doSomething();
});
Explanation:
Singletons give you more than just one instance through the whole application: their initialization is delayed till the first use. This is really a big thing when you deal with objects whose initialization is expensive. Expensive usually means I/O and in JavaScript I/O always mean callbacks.
Don't trust answers which give you interface like instance = singleton.getInstance(), they all miss the point.
If they don't take a callback to be run when an instance is ready, then they won't work when the initializer does I/O.
Yeah, callbacks always look uglier than a function call which immediately returns an object instance. But again: when you do I/O, callbacks are obligatory. If you don't want to do any I/O, then instantiation is cheap enough to do it at program start.
Example 1, cheap initializer:
var simpleInitializer = function(instanceReady) {
console.log("Initializer started");
instanceReady({property: "initial value"});
}
var simple = singleton(simpleInitializer);
console.log("Tests started. Singleton instance should not be initalized yet.");
simple(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
simple(function(inst) {
console.log("Access 2");
console.log("Current property value: " + inst.property);
});
Example 2, initialization with I/O:
In this example, setTimeout fakes some expensive I/O operation. This illustrates why singletons in JavaScript really need callbacks.
var heavyInitializer = function(instanceReady) {
console.log("Initializer started");
var onTimeout = function() {
console.log("Initializer did his heavy work");
instanceReady({property: "initial value"});
};
setTimeout(onTimeout, 500);
};
var heavy = singleton(heavyInitializer);
console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");
heavy(function(inst) {
console.log("Access 1");
console.log("Current property value: " + inst.property);
console.log("Let's reassign this property");
inst.property = "new value";
});
heavy(function(inst) {
console.log("Access 2. You can see callbacks order is preserved.");
console.log("Current property value: " + inst.property);
});
console.log("We made it to the end of the file. Instance is not ready yet.");
Christian C. Salvadó's and zzzzBov's answer have both given wonderful answers, but just to add my own interpretation based on my having moved into heavy Node.js development from PHP/Zend Framework where singleton patterns were common.
The following, comment-documented code is based on the following requirements:
one and only one instance of the function object may be instantiated
the instance is not publicly available and may only be accessed through a public method
the constructor is not publicly available and may only be instantiated if there is not already an instance available
the declaration of the constructor must allow its prototype chain to be modified. This will allow the constructor to inherit from other prototypes, and offer "public" methods for the instance
My code is very similar to zzzzBov's answer except I've added a prototype chain to the constructor and more comments that should help those coming from PHP or a similar language translate traditional OOP to JavaScript's prototypical nature. It may not be the "simplest" but I believe it is the most proper.
// Declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
"use strict";
// 'instance' and 'constructor' should not be available in a "public" scope
// here they are "private", thus available only within
// the scope of the self-executing anonymous function
var _instance=null;
var _constructor = function (name) {
this.name = name || 'default';
}
// Prototypes will be "public" methods available from the instance
_constructor.prototype.getName = function () {
return this.name;
}
// Using the module pattern, return a static object
// which essentially is a list of "public static" methods
return {
// Because getInstance is defined within the same scope
// it can access the "private" 'instance' and 'constructor' vars
getInstance:function (name) {
if (!_instance) {
console.log('creating'); // This should only happen once
_instance = new _constructor(name);
}
console.log('returning');
return _instance;
}
}
})(); // Self execute
// Ensure 'instance' and 'constructor' are unavailable
// outside the scope in which they were defined
// thus making them "private" and not "public"
console.log(typeof _instance); // undefined
console.log(typeof _constructor); // undefined
// Assign instance to two different variables
var a = Singleton.getInstance('first');
var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
// Ensure 'a' and 'b' are truly equal
console.log(a === b); // true
console.log(a.getName()); // "first"
console.log(b.getName()); // Also returns "first" because it's the same instance as 'a'
Note that technically, the self-executing anonymous function is itself a singleton as demonstrated nicely in the code provided by Christian C. Salvadó. The only catch here is that it is not possible to modify the prototype chain of the constructor when the constructor itself is anonymous.
Keep in mind that to JavaScript, the concepts of “public” and “private” do not apply as they do in PHP or Java. But we have achieved the same effect by leveraging JavaScript’s rules of functional scope availability.
You could just do:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// Whatever
}
})()
I think I have found the cleanest way to program in JavaScript, but you'll need some imagination. I got this idea from a working technique in the book JavaScript: The Good Parts.
Instead of using the new keyword, you could create a class like this:
function Class()
{
var obj = {}; // Could also be used for inheritance if you don't start with an empty object.
var privateVar;
obj.publicVar;
obj.publicMethod = publicMethod;
function publicMethod(){}
function privateMethod(){}
return obj;
}
You can instantiate the above object by saying:
var objInst = Class(); // !!! NO NEW KEYWORD
Now with this work method in mind, you could create a singleton like this:
ClassSingleton = function()
{
var instance = null;
function Class() // This is the class like the above one
{
var obj = {};
return obj;
}
function getInstance()
{
if( !instance )
instance = Class(); // Again no 'new' keyword;
return instance;
}
return { getInstance : getInstance };
}();
Now you can get your instance by calling
var obj = ClassSingleton.getInstance();
I think this is the neatest way as the complete "Class" is not even accessible.
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 = "I'm 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;
}
};
})();
For me the cleanest way to do so is:
const singleton = new class {
name = "foo"
constructor() {
console.log(`Singleton ${this.name} constructed`)
}
}
With this syntax you are certain your singleton is and will remain unique. You can also enjoy the sugarness of class syntax and use this as expected.
(Note that class fields require node v12+ or a modern browser.)
This is how I implement singleton pattern using ES6 features. Yes, I know this does not look like an Object-oriented approach, but I find this method is easy to implement and a clean way to implement.
const Singleton = (() => {
var _instance = !_instance && new Object('Object created....');
return () => _instance;
})();
//************************************************************************
var instance1 = Singleton();
var instance2 = Singleton();
console.log(instance1 === instance2); // true
This should work:
function Klass() {
var instance = this;
Klass = function () { return instance; }
}
I believe this is the simplest/cleanest and most intuitive way though it requires ECMAScript 2016 (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
I've found the following to be the easiest singleton pattern, because using the new operator makes this immediately available within the function, eliminating the need to return an object literal:
var singleton = new (function () {
var private = "A private value";
this.printSomething = function() {
console.log(private);
}
})();
singleton.printSomething();
Using ES6 classes and private static fields. Invoking new instances of the Singleton class will return the same instance. The instance variable is also private and can't be accessed outside the class.
class Singleton {
// # is a new Javascript feature that denotes private
static #instance;
constructor() {
if (!Singleton.#instance) {
Singleton.#instance = this
}
return Singleton.#instance
}
get() {
return Singleton.#instance;
}
}
const a = new Singleton();
const b = new Singleton();
console.log(a.get() === b.get()) // true
console.log(Singleton.instance === undefined) // true
function Once() {
return this.constructor.instance || (this.constructor.instance = this);
}
function Application(name) {
let app = Once.call(this);
app.name = name;
return app;
}
If you are into classes:
class Once {
constructor() {
return this.constructor.instance || (this.constructor.instance = this);
}
}
class Application extends Once {
constructor(name) {
super();
this.name = name;
}
}
Test:
console.log(new Once() === new Once());
let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');
console.log(app1 === app2);
console.log(app1.name); // Barfoo
Following is the snippet from my walkthrough to implement a singleton pattern. This occurred to me during an interview process and I felt that I should capture this somewhere.
/*************************************************
* SINGLETON PATTERN IMPLEMENTATION *
*************************************************/
// Since there aren't any classes in JavaScript, every object
// is technically a singleton if you don't inherit from it
// or copy from it.
var single = {};
// Singleton Implementations
//
// Declaring as a global object...you are being judged!
var Logger = function() {
// global_log is/will be defined in the GLOBAL scope here
if(typeof global_log === 'undefined'){
global_log = this;
}
return global_log;
};
// The below 'fix' solves the GLOABL variable problem, but
// the log_instance is publicly available and thus can be
// tampered with.
function Logger() {
if(typeof Logger.log_instance === 'undefined') {
Logger.log_instance = this;
}
return Logger.log_instance;
};
// The correct way to do it to give it a closure!
function logFactory() {
var log_instance; // Private instance
var _initLog = function() { // Private init method
log_instance = 'initialized';
console.log("logger initialized!")
}
return {
getLog : function(){ // The 'privileged' method
if(typeof log_instance === 'undefined') {
_initLog();
}
return log_instance;
}
};
}
/***** TEST CODE ************************************************
// Using the Logger singleton
var logger = logFactory(); // Did I just give LogFactory a closure?
// Create an instance of the logger
var a = logger.getLog();
// Do some work
// Get another instance of the logger
var b = logger.getLog();
// Check if the two logger instances are same
console.log(a === b); // true
*******************************************************************/
The same can be found on my gist page.
My two cents: I have a constructor function (CF), for example,
var A = function(arg1){
this.arg1 = arg1
};
I need just every object created by this CF to be the same.
var X = function(){
var instance = {};
return function(){ return instance; }
}();
Test
var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
Singleton:
Ensure a class has only one instance and provides a global point of access to it.
The singleton pattern limits the number of instances of a particular object to just one. This single instance is called the singleton.
defines getInstance() which returns the unique instance.
responsible for creating and managing the instance object.
The singleton object is implemented as an immediate anonymous function. The function executes immediately by wrapping it in brackets followed by two additional brackets. It is called anonymous because it doesn't have a name.
Sample Program
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
run()
Here is a simple example to explain the singleton pattern in JavaScript.
var Singleton = (function() {
var instance;
var init = function() {
return {
display:function() {
alert("This is a singleton pattern demo");
}
};
};
return {
getInstance:function(){
if(!instance){
alert("Singleton check");
instance = init();
}
return instance;
}
};
})();
// In this call first display alert("Singleton check")
// and then alert("This is a singleton pattern demo");
// It means one object is created
var inst = Singleton.getInstance();
inst.display();
// In this call only display alert("This is a singleton pattern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1 = Singleton.getInstance();
inst1.display();
let MySingleton = (function () {
var _instance
function init() {
if(!_instance) {
_instance = { $knew: 1 }
}
return _instance
}
let publicAPIs = {
getInstance: function() {
return init()
}
}
// this prevents customize the MySingleton, like MySingleton.x = 1
Object.freeze(publicAPIs)
// this prevents customize the MySingleton.getInstance(), like MySingleton.getInstance().x = 1
Object.freeze(publicAPIs.getInstance())
return publicAPIs
})();
I needed several singletons with:
lazy initialisation
initial parameters
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 the 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 in order for window[] to work, but with some simple typechecking, window.name and window.construct are also possible.

reusable javascript objects, prototypes and scope

MyGlobalObject;
function TheFunctionICanUseRightAwaySingleForAllInstansesAndWithoutInstanse() {
function() {
alert('NO CONSTRUCTOR WAS CALLED');
}
};
The Long-named function must be callable from MyGlobalObject, which in turn must be available as a global (to window) variable in all times after script was loaded. It should support extensibility in accordance with latest standards.
I'm at architectural dilemma of how to built JS base for an application (almost 100% JS).
We need an object i.e. window.MyObject (like a module, like jQuery) so
It can be created with
VAR1
var MyGlobalObjConstructor = function(){
this.GlobalFunctionInObject = function(){
alert('called with MyGlobalObj.GlobalFunctionInObject()');
}
};
window.MyGlobalObj = new MyGlobalObjConstructor();
Is MyGlobalObj extensible? Can I create child objects, which will inherit current state of MyGlobalObj (extended functions/properties MyGlobalObj.NewFunc e.g.)? What is the main difference between using prototype (VAR3)?
By GlobaldFunction I mean single instance for all initialized/instantiated (possibly instantializable) instances..
Or with
VAR2
var MyGlobalObj = {
GlobalFunctionInObject: function...
GlobalFunctionInObject2: function...
};
MyGlobalObj.GlobalFunctionInObject();
// here I lose all hierarchy elements, no prototype,
// can I use GlobalFunctionInObject2 in GlobalFunctionInObject?
Or with
VAR3
var MyGlobalConstuctor = function(){} // already 'well-formed' object
MyGlobalConstuctor.prototype.GlobalFunctionInObject = function...
};
var MyGlobalObj = new MyGlobalConstuctor();
// so I'm sceptical to NEW, because I have ALREADY wrote my functions
// which I expect to be in memory, single instance of each of them,
// so creating MyObject2,3,4 with NEW MyGC() makes no sense to me.
// DO I REALLY HAVE TO USE "MyGlobalConstuctor.prototype." FOR EACH FUNCTION?!!!!
What's the difference defining MyGlobalObj as a function and as an object (result of func or VAR2)?
OR VAR4?
I see in Chrome Debugger both prototype and __proto__ special fields. I've read that that's OK, but why are they not saved in a single prototype?
So, what is the correct/optimal way to implement window.MyObject, so one could MyObject.MyFunction(); What are the differences (pro/contra) of variants 1 2 and 3?
Variation 1 - Mixin
function SomeType() {
var priv = "I'm private";
this.publ = "I'm public";
this.action = function() {
return priv + this.publ;
};
}
var obj = new SomeType();
With this method you are creating a new object every time you call new SomeType(), creating all its methods and adding all this method to the new object. Every time you create an object.
Pros
It looks like classical inheritance so it's easy to understand to Java-C#-C++-etc people.
It can have private variables per instance since you have one function closure per each object you create
It allows multiple inheritance, also known as Twitter-mixins or functional mixins
obj instanceof SomeType will return true
Cons
It consumes more memory as more objects you create because with each object you are creating a new closure and creating each of it's methods again.
Private properties are private, not protected, subtypes can't access them
No easy way to know if a object has some Type as superclass.
Inheritance
function SubType() {
SomeType.call(this);
this.newMethod = function() {
// can't access priv
return this.publ;
};
}
var child = new SubType();
child instanceof SomeType will return false there is no other way to know if child has SomeType methods than look if it has them one by one.
Variation 2 - Object literal with prototyping
var obj = {
publ: "I'm public",
_convention: "I'm public too, but please don't touch me!",
someMethod: function() {
return this.publ + this._convention;
}
};
In this case you are creating a single object. If you are going to need only one instance of this type it can be the best solution.
Pros
It's quick and easy to understand.
Performant
Cons
No privacy, every property is public.
Inheritance
You can inherit a object prototyping it.
var child = Object.create(obj);
child.otherMethod = function() {
return this._convention + this.publ;
};
If you are on a old browser you will need to garantee Object.create works:
if (!Object.create) {
Object.create = function(obj) {
function tmp() { }
tmp.prototype = obj;
return new tmp;
};
}
To know if a object is a prototype of another you can use
obj.isPrototypeOf(child); // true
Variation 3 - Constructor pattern
UPDATE: This is the pattern ES6 classes are sugar syntax of. If you use ES6 classes you are following this pattern under the hood.
class SomeType {
constructor() {
// REALLY important to declare every non-function property here
this.publ = "I'm public";
this._convention = "I'm public too, but please don't touch me!";
}
someMethod() {
return this.publ + this._convention;
}
}
class SubType extends SomeType {
constructor() {
super(/* parent constructor parameters here */);
this.otherValue = 'Hi';
}
otherMethod() {
return this._convention + this.publ + this.otherValue;
}
}
function SomeType() {
// REALLY important to declare every non-function property here
this.publ = "I'm public";
this._convention = "I'm public too, but please don't touch me!";
}
SomeType.prototype.someMethod = function() {
return this.publ + this._convention;
};
var obj = new SomeType();
You can re-assign the prototype insteadd of adding each method if you are not inheriting and remember to re-assign the constructor property:
SomeType.prototype = {
constructor: SomeType,
someMethod = function() {
return this.publ + this._convention;
}
};
Or use _.extend or $.extend if you have underscore or jquery in your page
_.extend(SomeType.prototype, {
someMethod = function() {
return this.publ + this._convention;
}
};
The new keyword under the hood simply does this:
function doNew(Constructor) {
var instance = Object.create(Constructor.prototype);
instance.constructor();
return instance;
}
var obj = doNew(SomeType);
What you have is a function than has no methods; it just has a prototype property with a list of functions, the new operator means to create a new object and use this function's prototype (Object.create) and constructor property as initializer.
Pros
Performant
Prototype chain will allow you to know if a object inherits from some type
Cons
Two-step inheritance
Inheritance
function SubType() {
// Step 1, exactly as Variation 1
// This inherits the non-function properties
SomeType.call(this);
this.otherValue = 'Hi';
}
// Step 2, this inherits the methods
SubType.prototype = Object.create(SomeType.prototype);
SubType.prototype.otherMethod = function() {
return this._convention + this.publ + this.otherValue;
};
var child = new SubType();
You may think it looks like a super-set of Variation 2... and you'll be right. It's like variation 2 but with a initializer function (the constructor);
child instanceof SubType and child instanceof SomeType will return both true
Curiosity: Under the hood instanceof operator does is
function isInstanceOf(obj, Type) {
return Type.prototype.isPrototypeOf(obj);
}
Variation 4 - Overwrite __proto__
When you do Object.create(obj) under the hood it does
function fakeCreate(obj) {
var child = {};
child.__proto__ = obj;
return child;
}
var child = fakeCreate(obj);
The __proto__ property modifies directly the object's hidden [Prototype] property. As this can break JavaScript behaviour, it's not standard. And the standard way is preferred (Object.create).
Pros
Quick and performant
Cons
Non-standard
Dangerous; you can't have a hashmap since the __proto__ key can change the object's prototype
Inheritance
var child = { __proto__: obj };
obj.isPrototypeOf(child); // true
Comment questions
1. var1: what happens in SomeType.call(this)? Is 'call' special function?
Oh, yes, functions are objects so they have methods, I will mention three: .call(), .apply() and .bind()
When you use .call() on a function, you can pass one extra argument, the context, the value of this inside the function, for example:
var obj = {
test: function(arg1, arg2) {
console.log(this);
console.log(arg1);
console.log(arg2);
}
};
// These two ways to invoke the function are equivalent
obj.test('hi', 'lol');
// If we call fn('hi', 'lol') it will receive "window" as "this" so we have to use call.
var fn = obj.test;
fn.call(obj, 'hi', 'lol');
So when we do SomeType.call(this) we are passing the object this to function SomeCall, as you remember this function will add methods to object this.
2. var3: With your "REALLY define properties" do you mean if I use them in functions? Is it a convention? Because getting this.newProperty without it being defined at the same level with other member functions is not a problem.
I mean any property your object will have that is not a function must be defined on the constructor, not on the prototype, otherwise you will face one of the more confusing JS problems. You can see it here, but it's outside of the focus of this question.
3. Var3: what happens if I don't re-assign constructor?
Actually you might not see the difference and this is what makes it a dangerous bug. Every function's prototype object has a constructor property so you can access the constructor from an instance.
function A() { }
// When you create a function automatically, JS does this:
// A.prototype = { constructor: A };
A.prototype.someMethod = function() {
console.log(this.constructor === A); // true
this.constructor.staticMethod();
return new this.constructor();
};
A.staticMethod = function() { };
It's not a best practice because not everybody knows about it, but sometimes it helps. But if you reassign the prototype...
A.prototype = {
someMethod = function() {
console.log(this.constructor === A); // false
console.log(this.constructor === Object); // true
this.constructor.staticMethod();
return new this.constructor();
}
};
A.prototype is a new object, a instance of Object than prototypes Object.prototype and Object.prototype.constructor is Object. Confusing, right? :P
So if you overwrite the prototype and don't reset the "constructor" property, it will refer to Object instead of A, and if you try to use the "constructor" property to access some static method you may get crazy.
I usually settle with returning an object with functions as properties:
var newCat = function (name) {
return {name: name, purr: function () {alert(name + ' purrs')}};
};
var myCat = newCat('Felix');
myCat.name; // 'Felix'
myCat.purr(); // alert fires
You can have inheritance by calling the newCat function and extend the object you get:
var newLion = function (name) {
var lion = newCat(name);
lion.roar = function () {
alert(name + ' roar loudly');
}
return lion;
}
If you want a global cats object:
var cats = (function () {
var newCat = function (name) {
return {
name: name,
purr: function () {
alert(name + ' is purring')
}
};
};
return {
newCat: newCat
};
}());
Now you can call:
var mySecondCat = cats.newCat('Alice');

JavaScript Extending Class

I have a base class:
function Monster() {
this.health = 100;
}
Monster.prototype.growl = function() {
console.log("Grr!");
}
That I want to extend and create another class with:
function Monkey extends Monster() {
this.bananaCount = 5;
}
Monkey.prototype.eatBanana {
this.bananaCount--;
this.health++; //Accessing variable from parent class monster
this.growl(); //Accessing function from parent class monster
}
I've done quite a bit of research and there appears to be many convoluted solutions for doing this in JavaScript. What would be the simplest and most reliable way of accomplishing this in JS?
Updated below for ES6
March 2013 and ES5
This MDN document describes extending classes well:
https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript
In particular, here is now they handle it:
// define the Person Class
function Person() {}
Person.prototype.walk = function(){
alert ('I am walking!');
};
Person.prototype.sayHello = function(){
alert ('hello');
};
// define the Student class
function Student() {
// Call the parent constructor
Person.call(this);
}
// inherit Person
Student.prototype = Object.create(Person.prototype);
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// replace the sayHello method
Student.prototype.sayHello = function(){
alert('hi, I am a student');
}
// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true
Note that Object.create() is unsupported in some older browsers, including IE8:
If you are in the position of needing to support these, the linked MDN document suggests using a polyfill, or the following approximation:
function createObject(proto) {
function ctor() { }
ctor.prototype = proto;
return new ctor();
}
Using this like Student.prototype = createObject(Person.prototype) is preferable to using new Person() in that it avoids calling the parent's constructor function when inheriting the prototype, and only calls the parent constructor when the inheritor's constructor is being called.
May 2017 and ES6
Thankfully, the JavaScript designers have heard our pleas for help and have adopted a more suitable way of approaching this issue.
MDN has another great example on ES6 class inheritance, but I'll show the exact same set of classes as above reproduced in ES6:
class Person {
sayHello() {
alert('hello');
}
walk() {
alert('I am walking!');
}
}
class Student extends Person {
sayGoodBye() {
alert('goodBye');
}
sayHello() {
alert('hi, I am a student');
}
}
var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();
// check inheritance
alert(student1 instanceof Person); // true
alert(student1 instanceof Student); // true
Clean and understandable, just like we all want. Keep in mind, that while ES6 is pretty common, it's not supported everywhere:
ES6 gives you now the opportunity to use class & extends keywords :
Then , your code will be :
You have a base class:
class Monster{
constructor(){
this.health = 100;
}
growl() {
console.log("Grr!");
}
}
That You want to extend and create another class with:
class Monkey extends Monster {
constructor(){
super(); //don't forget "super"
this.bananaCount = 5;
}
eatBanana() {
this.bananaCount--;
this.health++; //Accessing variable from parent class monster
this.growl(); //Accessing function from parent class monster
}
}
Try this:
Function.prototype.extends = function(parent) {
this.prototype = Object.create(parent.prototype);
};
Monkey.extends(Monster);
function Monkey() {
Monster.apply(this, arguments); // call super
}
Edit: I put a quick demo here http://jsbin.com/anekew/1/edit. Note that extends is a reserved word in JS and you may get warnings when linting your code, you can simply name it inherits, that's what I usually do.
With this helper in place and using an object props as only parameter, inheritance in JS becomes a bit simpler:
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype);
};
function Monster(props) {
this.health = props.health || 100;
}
Monster.prototype = {
growl: function() {
return 'Grrrrr';
}
};
Monkey.inherits(Monster);
function Monkey() {
Monster.apply(this, arguments);
}
var monkey = new Monkey({ health: 200 });
console.log(monkey.health); //=> 200
console.log(monkey.growl()); //=> "Grrrr"
If you don't like the prototype approach, because it doesn't really behave in a nice OOP-way, you could try this:
var BaseClass = function()
{
this.some_var = "foobar";
/**
* #return string
*/
this.someMethod = function() {
return this.some_var;
}
};
var MyClass = new Class({ extends: BaseClass }, function()
{
/**
* #param string value
*/
this.__construct = function(value)
{
this.some_var = value;
}
})
Using lightweight library (2k minified): https://github.com/haroldiedema/joii
I can propose one variant, just have read in book, it seems the simplest:
function Parent() {
this.name = 'default name';
};
function Child() {
this.address = '11 street';
};
Child.prototype = new Parent(); // child class inherits from Parent
Child.prototype.constructor = Child; // constructor alignment
var a = new Child();
console.log(a.name); // "default name" trying to reach property of inherited class
This is an extension (excuse the pun) of elclanrs' solution to include detail on instance methods, as well as taking an extensible approach to that aspect of the question; I fully acknowledge that this is put together thanks to David Flanagan's "JavaScript: The Definitive Guide" (partially adjusted for this context). Note that this is clearly more verbose than other solutions, but would probably benefit in the long-term.
First we use David's simple "extend" function, which copies properties to a specified object:
function extend(o,p) {
for (var prop in p) {
o[prop] = p[prop];
}
return o;
}
Then we implement his Subclass definition utility:
function defineSubclass(superclass, // Constructor of our superclass
constructor, // Constructor of our new subclass
methods, // Instance methods
statics) { // Class properties
// Set up the prototype object of the subclass
constructor.prototype = Object.create(superclass.prototype);
constructor.prototype.constructor = constructor;
if (methods) extend(constructor.prototype, methods);
if (statics) extend(constructor, statics);
return constructor;
}
For the last bit of preparation we enhance our Function prototype with David's new jiggery-pokery:
Function.prototype.extend = function(constructor, methods, statics) {
return defineSubclass(this, constructor, methods, statics);
};
After defining our Monster class, we do the following (which is re-usable for any new Classes we want to extend/inherit):
var Monkey = Monster.extend(
// constructor
function Monkey() {
this.bananaCount = 5;
Monster.apply(this, arguments); // Superclass()
},
// methods added to prototype
{
eatBanana: function () {
this.bananaCount--;
this.health++;
this.growl();
}
}
);
For traditional extending you can simply write superclass as constructor function,
and then apply this constructor for your inherited class.
function AbstractClass() {
this.superclass_method = function(message) {
// do something
};
}
function Child() {
AbstractClass.apply(this);
// Now Child will have superclass_method()
}
Example on angularjs:
http://plnkr.co/edit/eFixlsgF3nJ1LeWUJKsd?p=preview
app.service('noisyThing',
['notify',function(notify){
this._constructor = function() {
this.scream = function(message) {
message = message + " by " + this.get_mouth();
notify(message);
console.log(message);
};
this.get_mouth = function(){
return 'abstract mouth';
}
}
}])
.service('cat',
['noisyThing', function(noisyThing){
noisyThing._constructor.apply(this)
this.meow = function() {
this.scream('meooooow');
}
this.get_mouth = function(){
return 'fluffy mouth';
}
}])
.service('bird',
['noisyThing', function(noisyThing){
noisyThing._constructor.apply(this)
this.twit = function() {
this.scream('fuuuuuuck');
}
}])
For Autodidacts:
function BaseClass(toBePrivate){
var morePrivates;
this.isNotPrivate = 'I know';
// add your stuff
}
var o = BaseClass.prototype;
// add your prototype stuff
o.stuff_is_never_private = 'whatever_except_getter_and_setter';
// MiddleClass extends BaseClass
function MiddleClass(toBePrivate){
BaseClass.call(this);
// add your stuff
var morePrivates;
this.isNotPrivate = 'I know';
}
var o = MiddleClass.prototype = Object.create(BaseClass.prototype);
MiddleClass.prototype.constructor = MiddleClass;
// add your prototype stuff
o.stuff_is_never_private = 'whatever_except_getter_and_setter';
// TopClass extends MiddleClass
function TopClass(toBePrivate){
MiddleClass.call(this);
// add your stuff
var morePrivates;
this.isNotPrivate = 'I know';
}
var o = TopClass.prototype = Object.create(MiddleClass.prototype);
TopClass.prototype.constructor = TopClass;
// add your prototype stuff
o.stuff_is_never_private = 'whatever_except_getter_and_setter';
// to be continued...
Create "instance" with getter and setter:
function doNotExtendMe(toBePrivate){
var morePrivates;
return {
// add getters, setters and any stuff you want
}
}
Summary:
There are multiple ways which can solve the problem of extending a constructor function with a prototype in Javascript. Which of these methods is the 'best' solution is opinion based. However, here are two frequently used methods in order to extend a constructor's function prototype.
ES 2015 Classes:
class Monster {
constructor(health) {
this.health = health
}
growl () {
console.log("Grr!");
}
}
class Monkey extends Monster {
constructor (health) {
super(health) // call super to execute the constructor function of Monster
this.bananaCount = 5;
}
}
const monkey = new Monkey(50);
console.log(typeof Monster);
console.log(monkey);
The above approach of using ES 2015 classes is nothing more than syntactic sugar over the prototypal inheritance pattern in javascript. Here the first log where we evaluate typeof Monster we can observe that this is function. This is because classes are just constructor functions under the hood. Nonetheless you may like this way of implementing prototypal inheritance and definitively should learn it. It is used in major frameworks such as ReactJS and Angular2+.
Factory function using Object.create():
function makeMonkey (bananaCount) {
// here we define the prototype
const Monster = {
health: 100,
growl: function() {
console.log("Grr!");}
}
const monkey = Object.create(Monster);
monkey.bananaCount = bananaCount;
return monkey;
}
const chimp = makeMonkey(30);
chimp.growl();
console.log(chimp.bananaCount);
This method uses the Object.create() method which takes an object which will be the prototype of the newly created object it returns. Therefore we first create the prototype object in this function and then call Object.create() which returns an empty object with the __proto__ property set to the Monster object. After this we can initialize all the properties of the object, in this example we assign the bananacount to the newly created object.
the absolutely minimal (and correct, unlike many of the answers above) version is:
function Monkey(param){
this.someProperty = param;
}
Monkey.prototype = Object.create(Monster.prototype);
Monkey.prototype.eatBanana = function(banana){ banana.eat() }
That's all. You can read here the longer explanation

Categories

Resources