How to write a singleton class in javascript 2009-09-30

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

If I look at my stats, a lot of people are wondering how to write a singleton class. I already wrote about it before but my old solution exposed the instance of the class so more than one instance could be created thus making it not completly a singleton class.

Here's the new solution using a private variable for the instance.


How to create an object with private variables and methods 2009-09-23

In short, you can use private variables when you return another scope when declaring a class.

function Cats() {
  var nameList = []; // private var
    
  // This is where you define another scope!
  return {
    add:function(name) {
      nameList.push(name);
    }
  } 
}

How does it work?

The magic lies in creating a different scope at the end of the class definition that does not include private variables. Then, private members are available in this scope and not outside of it, thanks to the power of closures.

Differences between private and public

These two classes definition shows the difference between the a class where all members are public versus a class where some members are private.

This is a class where all members are public.

function PublicCats() {
  // This is the list of cat names
  this.nameList = [];
  
  // This is a method that I would like to be private but can't
  // It returns the last cat of the list
  this.lastCat = function() {
    return this.nameList[this.nameList.length-1];
  }
  
  // Return the list of names
  this.names = function() {
    return this.nameList;
  }
  
  // Add a name to the list
  this.add = function(name) {
    this.nameList.push(name);
    
    // Return the last cat just added
    return this.lastCat();
  }  
}

This is the corresponding class where some members are private.

function PrivateCats() {
  // This is the list of cat names
  var nameList = [];
  
  // This is a private method
  var lastCat = function() {
    // Note : I don't use "this" to access private variables
    // thanks to the power of closures!
    return nameList[nameList.length-1];
  }
  
  // These are our public methods!
  // This is where we create another scope to
  // avoid external objects to use the private variables.
  return {
    add:function(name) {
      // Note : once again, I don't use "this" 
      // to access the private variables and methods
      nameList.push(name);
      return lastCat();
    },
    names:function() {
      return nameList;
    }
  }  
}

In the above code, line 15 makes all the difference between the two classes.

On GitHub

Get all the code on GitHub and see it live in action on my GitHub page.


How to use JSON (updated with example) 2009-09-16

This post is an update from the old post. A lot of things changed since it was written and the information in the old one is a bit outdated.

First of all, you should never use an eval() when using JSON because of security reasons that I will talk about later in another post. [edit : jQuery uses eval() but there's a work-around that will be talked about in another post.]

JSON and jQuery

The simplest way to use JSON is though jQuery. I have been using for more than 2 years and I never was disappointed.

Let's say I want to call Flickr search with JSON. It's simple :

$.getJSON(
    "http://api.flickr.com/services/rest/?jsoncallback=?",
    { method : "flickr.photos.search",
        api_key : "4ef2fe2affcdd6e13218f5ddd0e2500d",
        format : "json",
        tags : "landscape",
    },
    ajaxCallBack
);

The $.getJSON takes 3 parameters.

1. The URL The URL of the remote call.

2. The parameters The parameters to complete the call. On the documentation page about this Flickr method, you have a list of all the parameters you can use. For a JSON call on Flickr, you have to send the api_key and the format. I added the parameter tags to send me all photos that are tagged landscape.

3. The callback Most API services now requires a callback, a method that will be called when the JSON is loaded. It is more secure and easier to work with. At the end of the first parameter (the URL), I added jsoncallback=? (flickr called this parameter jsoncallback but it could be named differently on other services). This is the jQuery-way of saying “When you finish loading the JSON, call the method specificied by the third argument”.

You may wonder how Flickr knows which function to use on callback. It's because in jQuery, there's a special case for that. In the URL, you can see that the jsoncallback is written like that jsoncallback=?. The ? is replaced by your own callback method (in my case, I called it ajaxCallback)

The callback method

The callback method I used looks like this :

function ajaxCallBack(data) {
    // Loop throught all photos and display them
    // it uses the jquery.each method 
    // doc at http://docs.jquery.com/Utilities/jQuery.each
    $.each(data.photos.photo, function(photoIdx, photo) {
        // Build the thumbnail url
        var thumb_url = ["http://farm", photo.farm, ".static.flickr.com/", 
            photo.server, "/", photo.id, "_", photo.secret, "_t.jpg"].join("");
        
        // Build the photo url
        var photo_url = ["http://www.flickr.com/photos/", 
            photo.owner, "/", photo.id].join("")

        // Build HTML
        $("body").append(
            $("")
                .attr("href", photo_url)
                .attr("target", "_blank")
                .append(
                    $("").attr("src", thumb_url)
                )
        )
    });
}

If you know jQuery a little, it simply creates the HTML to show the thumbnails and a link to the photo.

Get the code

You can get the complete code for this example on GitHub and a working example.


Easy loop for every element of an array 2009-05-12

There's something bugging me with javascript for loop : the extra work to loop though all elements of an array. Suppose I want to alert each element of an array, there are three ways of doing it.

First, you loop with an index and assign the element to a variable.

var items = ["a", "b", "c"];
for (var i = 0; i < items.length; i++) {
  var item = items[i];
  alert(item);
}
You always have to have that extra assignment at the beginning of the loop.

Second, you loop with a for each.

var items = ["a", "b", "c"];
for (var i in items) {
  var item = items[i];
  alert(item)
}
In javascript, the for each loops though the index of the array instead of looping though the elements, like in most other languages. Thus, you also have to make the extra assignment at the beginning of the loop.

The easiest way of doing it is the third one.

var items = ["a", "b", "c"];
for (var i = 0, item; item = items[i]; i++) {
  alert(item);
}

How does it work? First it uses multi-assignment on one line. In javascript, you could write var i = 0, j = 1; and it would create two variables, i and j.

The second part of the for is confusing : it assigns the item but it never check if i it is out of bounds of the array (using i < items.length). It works because when javascript tries to assign an item after the end of the array (in our case items[3]), it returns null which is considered by javascript as false.


Be ahead of the trend, try CouchDB 2009-01-12

I always loved and hated databases. When I was a younger programmer, I asked to switch to DB administrator and, thank God, they didn't agree to let me mutate in a DBA. I ended up fired like 80% of the company (except the DBA). In fact, I wanted to be DBA because I thought I knew how to work with a DB better than them. The rest of my life proved me wrong. Nobody knows what they're doing because relational databases are a mess.

Then came the non-relational database. Amazon's SimpleDB was the first NRDBMS (as opposed to RDBMS) that got a public attention. When I read the specs, I really thought it was cool but I wondered “Is it scalable?”. Then I remembered that there is no such thing as a scalable database. Databases need to be smashed and hurt in order to be as scalable as we want them to. I wanted to give it a try but I wasn't ready to pay for it yet.

Working with xmpp/jabber, I saw a post by the well-known metajack (his blog is mainly about xmpp) about couchdb and I knew the time as come for me to be different. I had to try it so I opened a terminal and wrote sudo apt-get install couchdb. This was the beginning of a great adventure for me…

What's the link between CouchDB and Javascript? CouchDB is completly JSON. You can write an application that is completly JSON/Ajax without a single line of PHP/Ruby/Python/whatever.

I'm currently writing a simple app for CouchDB and this is the first of some posts about writing an app with CouchDB. I currently use version 0.8.0 and I ran through a lot of problems and I wish these posts will help you succeeding in building an application supported by CouchDB without all the hassle I went through.

Because my main project is TimmyOnTime (and don't forget to check out our new blog behind the clock), I will work partial-time on this project so it might not go as fast as I (and you) want. But don't despair, you will still be ahead of the trend when NRBDMS will go mainstream.