Classes and Instances in Javascript

I was reading a question about what every Javascript programmer should know on StackOverflow and found this useful pattern for using the more classic class/instance pattern instead of Javascript’s standard prototype method. I found the last example to be quite elegant and want to preserve it here for reference.

function Shape(x, y) {
    var self = {};

    self.x = x;
    self.y = y;

    self.toString = function() {
        return 'Shape at ' + self.x + ', ' + self.y;
    };

    return self;
}

function Circle(x, y, r) {
  var self = Shape(x, y);

  self.r = r;

  var _baseToString = self.toString;
  self.toString = function() {
    return 'Circular ' + _baseToString(self) + ' with radius ' + r;
  };

  return self;
};

var mycircle = Circle(2, 3, 5);
console.log(mycircle.x === 2);
console.log(mycircle.y === 3);
console.log(mycircle.r === 5);
console.log(mycircle.toString());

With this pattern you have to use the ‘self’ variable (which you can name anything you wish, the original was named ‘that’) to access and modify attributes of the class just like in Python. Unlike Python you must explicitly declare the self variable at the beginning of the class and return it at the end. Also if you are going to override an attribute in the parent class, but still need to access the parent attribute, you must rename it before overriding it, otherwise the reference to self.toString will end up in an infinite recursive loop.

Advertisements

One thought on “Classes and Instances in Javascript

  1. Quite interesting… There’s a couple potential issues I can see with the code above, however:

    First, the toString functions will be created every time the Shape or Circle function is used to create an object. At best, this is a minor memory leak. At worst (in a game which instant items a ton of these objects, for example) it can really drag down performance. To solve this, you could have the toString function stored somewhere outside of these factory methods (in Shape.toString, for example), and simply set a toString property on the newly created object to point to the pre-made toString function.

    Second, in Circle’s toString overridden method, you are passing in ‘self’ to the original toString method. This works because the Shape-created toString function has self in it’s scope, pointing to the newly created object. However, as it has no argument using the parameter ‘self’, you don’t need to pass it in.

Comments are closed.