Posts Tagged ‘singleton’

Singleton without a closure

Saturday, July 17th, 2010

Warning: anti-pattern ahead.

Mwahaha, I feel like a ninja. I mean a ninja by Doug Crockford's definition which means someone who finds a mistake in the language's design, decides it's cool and abuses it.

So there you go. Regular expression objects are created only once if you're using a literal. Such an object can be used to store the single instance of a Singleton() constructor.

Implementation

function Single() {
    "strict me not!";
 
    var re = / /;
    if (re.instance) {
        return re.instance;
    }
    re.instance = this;
    this.name = "Foo";
 
}
 
Single.prototype.getName = function () {
    return this.name;
};

Test

var s1 = new Single(),
    s2 = new Single();
 
console.log(s1 === s2); // true
console.log(s1.getName()); // "Foo"
s1.name = "dude";
console.log(s2.getName()); // "dude"

Pros

  • The prototype chain works fine
  • No closures
  • No public properties or globals to store the single instance

Cons

  • It's a hack
  • ES5 defines that reg exp literals should no longer work like this

Verdict

Don't use. Please :)

Singleton

Monday, September 14th, 2009

According to Wikipedia:

...the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object.

How does this apply to JavaScript? Well, in JavaScript there are no classes, just objects. So when you create a new object, there's no other object like it and the new object is already a singleton.

var obj = {
  myprop: 'my value'
};

This is an example of creating a simple object in JavaScript using the object literal and it's also an example of a singleton.

Using new

The other question is how about if you want to use the Java-like syntax:

var obj = new Constructor();

This is more of classic-like syntax so the idea of a singleton here is that when you use new to create several objects using the same constructor, you should only get one object.

var obj = new Constructor();
var obj2 = new Constructor();
alert(obj === obj2); // true

obj is created only the first time the constructor is called, the second time (and the third, fourth, etc) the obj created the first time is returned. How to achieve this in JavaScript?

Basically you need your Constructor to cache the object instance this once it's created and then pull this instance the second time it's called. You can cache the object instance:

  • in a global variable - not recommended, general principle is that globals are bad, plus anyone can overwrite this global, even by accident;
  • in a Constructor property - functions in JavaScript are objects, so they can have properties. You can have something like Constructor.instance and cache the object there. This is a nice clean solution with the only drawback that this property is accessible and code outside of yours might change it, so you lose the instance;
  • wrap the instance in a closure

Let's take a look at an example implementation of the last option.

function Constructor() {
  return Constructor.getInstance(this);
}
Constructor.getInstance = function(){
  var instance;
  return function(that) {
    if (typeof instance === 'undefined') {
      instance = that;
    }
    return instance;
  }
}();

And a simpler new

Here's another way to do the class-like singleton. Secret sauce: using a closure to keep the reference to the single object and then rewrite the constructor.

function Single() {
 
  var instance = this; 
 
  // add more to this…
 
  Single = function (){
    return instance;  
  };
}
 
// test
var my1 = new Single();
var my2 = new Single();
alert(my1 === my2) //true