Generic Singleton Factory in JavaScript

I recently contributed this little tidbit to stackoverflow’s Hidden Features of JavaScript and thought it would be best to elaborate it on it fully. In a recent client project, I needed a generic method to produce singleton instances of interface widgets.  This is the method that I came up with and it works pretty well. Before we begin, these are not singleton classes in the normal sense, but a generic singleton factory.

Edit: Singletons are generally considered an anti-pattern.  Use them at your own discretion.

Lets get started, piece by piece.   First off, we need a means of storing instances internally.  To do that, we create a closure and return a new function that will actually do the work:

It doesn’t do much, but there you have it.  Now that we have somewhere to store our instances, lets finish out the function by instantiating new objects (only once of course) and returning those singleton instances.

And that’s it.  Notice the new window[objectName]();.  In JavaScript, you can access objects in the global scope by name by referencing them as properties of the global  window object.

Consider the following two example constructors:

Basic usage of our fancy new generic singleton factory is as follows:

So far, getInstance works in simple cases, but if you’re in an environment where you’re using nested objects to facilitate namespacing (as in getInstance("com.project.widgetAbc")), then this method falls a little short. However, there is a simple solution.

I think the comments spell out the changes fairly well, but lets give it a once-over just to be sure.  The major change is that objectName is split on the member operator (.), yielding any array like ["com", "project", "widgetAbc"].  We then iterate through that array, linking each member to the previous, starting from the global object, window, until we reach the end of the chain.  This gives us an instantiable reference to the requested object.

Lastly, you’ll notice that on the line, instances[objectName] = new object;, I omitted the ().  It works with or without the parenthesis, but I prefer to omit them to distinguish the fact that we are not instantiating an object called “object”, but instead, are instantiating the object referenced by the variable object.

Now that we have all that settled, we can use our factory as follows:

I hope that shed some light on the subject.  Feel free to ask a question or two, and don’t hesitate to tell me if I made any mistakes that need correcting.

 

Hi there, I'm Justin!

I like to teaching people about programming. Well, yeah, I guess it's obvious, I also like to write. Yes that was a Digital Underground reference.