How to make a singleton in javascript 2007-04-04

[UPDATE : This post is outdated. Check out the new post on singletons.]

Singleton is one of the most common and easiest design pattern. In fact, a lot of designs are wrong just because the developer didn't know about singletons and design patterns (I could have said : a lot of my designs were wrong just because I didn't know about singletons and design patterns).

I was looking at the first three results for singleton javascript on Google and I was more than deceived by what they had to tell us. That's why I write this article.

What is a singleton class?

A singleton is when your application needs to use just one instance of an object to centralize your access to it. Example, I have a list of cat names that can be used in various functions of an application. Sometimes, names are added or removed. I could use a global variable to the page containing the list. The problems are :

  • It's a global variable (global variables are bad).
  • I don't know when the list is created or initialized.
  • If you reuse your class in another project, you will always need to define a global variable and instance it correctly.
  • It's ugly.

If I use a singleton pattern, the advantages are :

  • The object is always correctly created.
  • You don't have to ask yourself questions about the state of the list or whatever. It just works!
  • Another programmer can recognize the singleton pattern thus making it easier for him to work.

    How to write a singleton class

    Before writing a singleton, you need to know about creating objects and static functions.
// I create the class
function CatNames() {
    this.names = new Array(); // The array that will contain the names
}

CatNames.instance = null; // Will contain the one and only instance of the class

// This function ensures that I always use the same instance of the object
CatNames.getInstance = function() {
    if (CatNames.instance == null) {
        CatNames.instance = new CatNames();
    }

    return CatNames.instance;
}

// Function to add a cat name
CatNames.prototype.add = function(catName) {
    this.names.push(catName);
}

// Function to remove the last cat name
CatNames.prototype.removeLast = function() {
    return this.names.pop();
}

// Function to alert all cat names
CatNames.prototype.alertAllCats = function() {
    alert(this.names.join(","));
}

I use it in these functions.

function addThreeNames() {
    // I use the one and only instance of the class (the magic of singletons)
    var names = CatNames.getInstance();

    names.add("Mistigri");
    names.add("Bibi");
    names.add("Gary");
}

function removeLastCat() {
    // Once again, singleton is here
    var names = CatNames.getInstance();

    names.removeLast();
}

// I call the functions
// - no need for a global variable
// - no need to create the object and pass it as parameter
addThreeNames();
removeLastCat();

// Alert all cats
var names = CatNames.getInstance();
names.alertAllCats();

The downside of this technique

Yes I know, you can instantiate the singleton class if you want.

var catNames = new CatNames();

You know what? You'll have to follow a simple rule : never instantiate a singleton class. Maybe we could use more techniques that would protect you from instantiating your own singleton class but it would be a waste of time and code.


Do not use the style property on HTML objects 2007-04-03

Since ajax, a lot of people have to create HTML on the fly depending on response of the request. One mistake that I see a lot is that people are using the style property of their HTML objects. Why shouldn't I do it?

The style property has a precedence on every style

Because the style property is so “close” to the HTML object, it will override every other style from a CSS file. So if you begin to write styles in your javascript code, you'll have to do it all the time. It might be easy and clean for a basic project but it will become a mess in the future. You should centralize every style in your CSS files so you won't have to search where you assigned a style.

Example

I have this CSS

[source:css] div.theCssClass { background-color:blue; } [/source]

and I create a new HTML object of this class

[source:javascript] // I create the DIV var div = document.createElement(“div”); div.appendChild(document.createTextNode(“This div is a test”));

div.className = “theCssClass”; // I assign theCssClass div.style.backgroundColor = “red”; // The background is red

document.body.appendChild(div); [/source]

You'll see that the even if I set the background color to blue in the CSS file, the background will be red because I used the style property.

The !important in CSS

If you want to override a style assigned in javascript, you could always use the !important statement in your CSS file.

[source:css] div.useThisOne { background-color:blue !important; } [/source]

Use it only if you really have to. I wouldn't recommend !important because it breaks the default behavior of styles and can become very messy. When all is important, nothing is important.


Looping through object properties and hash tables using the “in” statement 2007-04-01

As I said earlier, objects are hash tables of properties and functions so looping throught them is done the same way (weepee!).

The “in” statement

The in statement must be used in a for loop. Like this : for (var element in allElements). In most of the other languages, the element variable would contain the complete element but in javascript, it contains the name that refers to the complete element.

Looping through a hash table

Before doing it, maybe you should take a look at How to use javascript hashes (or hash-table) to make sure you fully understand what are javascript hash tables.

[source:javascript]

// I create a hash table var hashPetNames = new Object();

// I create the pets hashPetNames[“cat”] = “Mistigri”; hashPetNames[“dog”] = “Rex”; hashPetNames[“bird”] = “Bibi”;

// I loop using the “in” statement for (var name in hashPetNames) { alert(“My ” + name + “'s name is ” + hashPetNames[name]); }

[/source]

Run this code and you should see the alerts : - My cat's name is Mistigri. - My dog's name is Rex. - My bird's name is Bibi.

So easy.

Looping through an object

This one is a little kinkier. Why would I want to loop through an object properties and methods? I can't give you an answer. It's up to you to find it. I've used it a couple of times so it's not as useless as you could think.

Example, I would like to separatly alert all the properties and methods of an object.

[source:javascript]

// Create the class function TheClass() { this.name = “The class”; this.fullName = “The full name of the class”; this.age = “51”; }

// Add a function TheClass.prototype.alertClass = function() { alert(this.name + “ ” + this.fullName + this.Age); }

// Construct the object var theObject = new TheClass();

// Loop through the properties/functions var properties = “”; for (var propertyName in theObject) { // Check if it's NOT a function if (!(theObject[propertyName] instanceof Function)) { properties += propertyName + “, ”; } }

alert(“Properties : ” + properties);

// Loop through the properties/functions var functions = “”; for (var functionName in theObject) { // Check if it's a function if (theObject[functionName] instanceof Function) { functions += functionName + “, ”; } }

alert(“Functions : ” + functions);

[/source]


How to use javascript hashes (or hash-table) 2007-03-29

Javascript has no hash table object. In fact, all objects are hashes.

var hashPetName = new Object();
hashPetName["dog"] = "Rex";
hashPetName["cat"] = "Mistigri";

console.log("My dog's name is " + hashPetName["dog"]
    + " and my cat's name is " + hashPetName["cat"] );

It's a little overwhelming to write it like that so let's use a simpler form.

var hashPetName = {
  dog: "Rex",
  cat: "Mistigri"
}

console.log("My dog's name is " + hashPetName["dog"]
    + " and my cat's name is " + hashPetName["cat"] );

Great! That's it about javascript hashes, now I can go groom my cat.

Wait!!!

Why can I use an object to emulate a hash? Can I do the same thing with a Number object? Let's try with the same code than above but with a Number instead of an Object.

[source:javascript] var hashPetName = new Number(); // Magic is here! hashPetName[“dog”] = “Rex”; hashPetName[“cat”] = “Mistigri”;

alert(“My dog's name is ” + hashPetName[“dog”] + “ and my cat's name is ” + hashPetName[“cat”] ); [/source]

It works!!! What can we understand of this?

All objects are hashes too

When you are javascripting, forget everything you know about other languages, it won't be any help. I'm adding to the list
  • All objects are hashes
When we create an object, its properties and methods are added to the hash of the object.

[source:javascript] // Create a class function TheClass() { // Adding a property this.name = “the name”; }

// Create the object theObject = new TheClass();

// Alert the property name alert(theObject.name);

// Alert the property name using the hash alert(theObject[“name”]); [/source]

In this example, you see that using theObject.theProperty is the same thing that using theObject[“theProperty”].

Dynamically add a property/method to the object

In my first example, I didn't create the property in the constructor before using it. As you saw, it's easy to dynamically add a property or a method.

[source:javascript] // Create a class function TheClass() { }

var theObject = new TheClass();

theObject[“age”] = 3; // Create a new 'age' property theObject.fullName = “Mistigri”; // Create a new 'fullName' property

theObject.alertDetail = function() { alert(this[“fullName”] + “ is ” + this.age); }

theObject“alertDetail”; [/source]

Beware! The new property/method will only be available to the instance you're working on. If you want to add a new property/method to every instances of the class, use prototypes.

Using an array thinking it's a hash

One of the most common mistake I see is to use an Array object thinking that's the only one that you can use the brackets to create a hash. Even if it works, it's not how it should be done. I recommend the use of Object instead.

[Update : A friend of mine pointed me out that I should have talked about hash tables (or associative arrays) instead of hashes.]


How to write constants in javascript 2007-03-28

YOU CAN'T. As simple as that. Anyway, what is a constant? A constant is a unchangeable variable that throws an error when you try to write in it. Thus, implementing constant in javascript would be against its will to be opened. The magic of javascript resides in the liberty it gives you to change anything you want, anywhere you want. Even if you're not the owner of the object. Even if it's a javascript intrinsic class. Why would you want to have constants???

Still, everyone wants to use constants (myself included). Here are a couple of ways of doing it without actually doing “it”.

Global constants

Ouch! That one hurts! As I said earlier, global variables are prohibited since 1992 by GVIP (Global Variables International Police). But sometimes, a man gotta do what a man gotta do. If you really can't find any better solution, use this one.

[source:javascript] var DISPLAYTYPESMALL = 0; var DISPLAYTYPEBIG = 1; [/source]

Class constant

If you already know how to create objects you have to use the class functions technique (also knows as static or shared functions) to create a class “constant”.

[source:javascript] // Create the class function TheClass() { }

// Create the class constant TheClass.THE_CONSTANT = 42;

// Create a function for TheClass to alert the constant TheClass.prototype.alertConstant = function() { // You can't access it using this.THECONSTANT; alert(TheClass.THECONSTANT); }

// Alert the class constant from outside alert(TheClass.THE_CONSTANT);

// Alert the class constant from inside var theObject = new TheClass(); theObject.alertConstant(); [/source]

As you saw, you can't access the constant using the this variable (a reference to the current object) because the constant is defined on the class only and not the object.

Class enum

Sometimes, constants are not enough. You need to regroup them to be more logical. Example? I have three different display type : small, medium, big. I could do this

[source:javascript] // Create the class function TheClass() { // Initialize the display type to big this.displayType = TheClass.DISPLAYTYPEBIG; }

// Create constants TheClass.DISPLAYTYPESMALL = 0; TheClass.DISPLAYTYPEMEDIUM = 1; TheClass.DISPLAYTYPEBIG = 2;

// Assign the small display type to the object var theObject = new TheClass(); theObject.displayType = TheClass.DISPLAYTYPESMALL; [/source]

It works but they are not logically grouped. I would prefer to use an enumeration (enum) [more info about enum].

[source:javascript] // Create the class function TheClass() { // Initialize the display type to big this.displayType = TheClass.DISPLAY_TYPE.big; }

TheClass.DISPLAY_TYPE = { small : 0, medium : 1, big : 2 }

// Assign the small display type to the object var theObject = new TheClass(); theObject.displayType = TheClass.DISPLAY_TYPE.small; [/source]

This is what I call beautiful code.

One simple rule

Knowing that there's no mechanism that prevents you from modifying your “constants”, follow that simple law : don't modify your constants.