Sep 24 2009

Singletons in JavaScript

Category: JavaScript, PHPJonathan Fingland @ 4:13 pm

I use singletons all over the PirateQuesting code, but I’ve never explained the idea here, nor how they are different from singletons in other languages.

Anyone familiar with common design patterns knows how singletons work in the vast majority of languages. For a PHP example, see this post.

In JavaScript there are basically two main ways to create a singleton. One is use immediate instantiation so that the class may not be instantiated again. The second is closer to the traditional singleton pattern, however, since there are no private members or constructors, we can get around this by using a nested ‘class’ constructor — and there are two ways to accomplish this.

The first way is done as follows:

var singleton = new (function Singleton() {
                               this.value = 12;
                             } )();

alert(singleton.value); // alerts 12;

var singly = new Singleton(); // Singleton is not defined.

alert(singleton instanceof Singleton); // Singleton is not defined

In the above, the constructor name, Singleton, isn’t really necessary. While it can’t be used to instantiate the Singleton again, it also can’t be used with instanceof or typeof so feel free to leave it out if you want; leaving it in, does make it more obvious what is happening though.

And the second way (version 1):

var Singleton = (function () {
  var instance = null;

  function Singleton() {
    this.value = 12;
  }

  this.getInstance = function () {
    if (instance === null) {
      instance = new Singleton();
    }
    return instance;
  }
})();

var singleton = Singleton.getInstance();
alert(singleton.value); // alerts 12;

var singly = new Singleton(); // Singleton is not a construct

alert(singleton instanceof Singleton); //invalid 'instanceof' operand Singleton

The above is just an anonymous function being called immediately (note the () after the function declaration). Inside the function it declares a pseudo-private member called instance, a pseudo-private constructor, Singleton, and a getInstance method. The getInstance method can see instance due to closure, while the outside world has no idea that it exists.

And finally, the second way (version 2):

var Singleton = {

  getInstance : (function() {

    var instance;
    function Singleton() {
      this.value = 12;
    }

    return function () {
      if (instance == null) {
	    instance = new Singleton();
      }
      return instance;

    }

  })()
}

var singleton = Singleton.getInstance();
alert(singleton.value);

var singly = new Singleton(); // Singleton is not a constructor

alert(singleton instanceof Singleton); //invalid 'instanceof' operand Singleton

In this final example, all of the logic is put into the getInstance function which is the result of a self-calling function which itself returns a function. Yeah, it’s a little hard to follow, but basically the returned function has visibility of instance and the Singleton constructor due to closure.

As a closing note, it’s worth pointing out that although all of the above methods do not permit a second instance construction, they also do not allow use of typeof or instanceof for type verification.

Update

Based on a comment below by Peter Robinett, I’ve come up with a different way to do this, which allows for instanceof and typeof and seems to be an all-round good solution to the problem. It does not, however use the classical getInstance method, but works well all the same.

var Singleton = function () {
  var instantiated = false;

  return function () {
    if (instantiated) {
      throw "Singleton already instantiated";
    }
    instantiated = true;
    this.value=12;
    }
}()

var singleton = new Singleton();
alert(singleton.value);    //alerts 12
alert(singleton instanceof Singleton);  alerts true 

var singly = new Singelton(); //throws exception and cannot be instantiated

Tags: , ,


Dec 01 2008

Functions in Closures

Category: DOM, JavaScriptJonathan Fingland @ 7:47 am

I last wrote about closures and how this affects the visibility of variables and functions. This time I’m going to introduce returning functions from a closure and how it can be useful in the first part.

First off, lets say you have a strange need to create functions to consistently add a value like addFive, addTen, etc. Well this is one way to go about it.

function createAdder(addition_size) {
      return function (value) {
                     return value + addition_size;
               }
}

var addFive = createAdder(5);
var addTen = createAdder(10);

alert(addFive(3));
alert(addTen(-10));

The code above will alert 8 and 0. While this isn’t the most natural use of the technique, hopefully it is clear enough. addition_size is retained by the addFive and addTen functions because the function had visibility when it was declared.

One handy way to use this is when creating event handlers that need to take parameters. When adding a handler, you pass the function itself, which doesn’t provide an opportunity to add extra parameters, we can get around this by doing:

function getValuePlusFiveDisplayer(value) {
  return function (event) {
    var sum = addFive(value);
    alert(value + " + 5 = " + sum);
  }
}

var number_1 = document.getElementById("number_1");
number_1.addEventListener("click",getValuePlusFiveDisplayer(1),false);

var number_2 = document.getElementById("number_2");
number_2.addEventListener("click",getValuePlusFiveDisplayer(2),false);

And HTML like:

<span id="number_1" class="number_button">1</span>
<span id="number_2" class="number_button">2</span>

Which would work like this:

12

Even though you’re unlikely to need this exact example, hopefully it gives you some ideas, or helps solve some problems

Tags: ,