Thursday, August 4, 2011

Object Oriented Javascript

Suppose we need to create a counter that starts at zero, increments to 4 and then restarts at 0 (A "you can't count to five" counter). There many ways to do this, but a straightforward way someone might do this in javascript would be:
var global_count = 0;
function increment() {
    global_count ++;
    if (global_count > 4) {
        global_count = 0;
    }
}

This is pretty common for beginners and works until your systems start to get complicated and your global_count gets clobbered or multiple people need to have counters. For multiple counters, one might start with a naming convention and add variables like "global_count2, global_count3" and et cetera. This doesn't solve the problem of the variables getting clobbered in other parts of your system and it likely makes it worse because now there are more permutations to mix up and accidentally change the value of.

As an example of what I'm talking about
var global_count = 0;
function increment(my_val) {
    my_val++;
    if (my_val > 4) {
        my_val = 0;
    }
}

increment(global_count); //works fine

//Somewhere else a smart guy decides to do this
global_count = 52;


To prevent this sort of thing OO has the concept of information hiding. In java, a straightforward way to avoid someone clobbering your count is to encapsulate the "count" variable and only access it via a method that performs your business logic.
public class BeanCounter() {
  private int count = 0;

  public void increment() {

    count++;
    if (count > 4) {
       count = 0;
    }
  }
  public int getCount() {
    return count;
  }
}

So now, when this java example is literally (for the most part) translated to javascript, it looks like this:
function BeanCounter() {
    var count = 0;

    this.increment = function() {
        count++;
        if (count > 4) {
           count = 0;
        }
    }

    this.getCount = function() {
        return count;
    }

}
var my_counter =new BeanCounter();

But a more javascripty way to do this would probably be:
var bean_counter = function () {
    var that = {};
    var count = 0;
    that.increment = function () {
        count++;
        if (count > 4) {
           count = 0;
        }
    };
    that.getCount = function () {
        return count;
    };
    return that;
};
var my_count = bean_counter();
my_count.increment();
my_count.getCount();

In both these examples, we can see some key differences between javascript and java. First, there really isn't anything formally defining a "class". We simply have functions with different mechanisms to extend and enhance them. In addition, there's more than one way to actually implement something that could fulfill some of capabilities that a more traditional OO language (like java) might give us. In this case the thing we wanted was the ability to ensure we could have things that would only be able to count to 4, then reset back to 0.

There are some advantages to the second approach when it comes to inheritance and polymorphic behavior that I won't go into here, but for a more in-depth look at different ways to apply (and mis-apply) OO concepts in javascript, I highly recommend Javascript, The Good Parts by Douglas Crockford.

No comments: