Automatic getters and setters in Javascript

When you’re working with object oriented code, writing those dumb getters and setters can be a bit of a pain, since they’re just getting and setting simple values most of the times. So I thought I’d bring in some magic to my Javascript classes to generate these methods.

I’m using John Resigs Simple Javascript Inheritance to emulate class inheritance in Javascript, so you might want to check that out.

So the first step is to create a base class that takes care of the getters and setters for us.

var DomainObject = Class.extend({
  init: function() {
    /**
     * Generating getters and setters for the domain object by looping over
     * all properties that start with _ and automatically creating getters/setters
     * If the property is "_first_name", the getter will become "firstName()", and
     * the setter will become "setFirstName()"
     */
    for(var key in this) {
      createGettersAndSetters(key, this);
    }
    function camelize(str) {
      var ret = '';
      for(var i = 0; i < str.length; i++) {
        var chr = str.charAt(i);
        if(chr != '_') {
          ret += chr;
        } else {
          i++;
          ret += str.charAt(i).toUpperCase();
        }
      }
      return ret;
    }
    function createGettersAndSetters(key, context) {
      if(key.indexOf('_') === 0 && typeof context[key] != 'function') {
        var set_method = 'set'+ camelize(key);
        // Make sure we don't override an existing setter
        if(!context[set_method]) {
          context[set_method] = function(value) {
            context[key] = value;
          }
        }
        // Using substr to remove the starting _, since we don't want the
        // string to start with a capital letter, as we do with the setters
        var get_method = camelize(key.substr(1));
        // Make sure we don't override an existing getter
        if(!context[get_method]) {
          context[get_method] = function() {
            return context[key];
          }
        }
      }
    }
  }
});

So now that we’ve got our class that handles the magic, we need to test it!

var User = DomainObject.extend({
  _id: false,
  _name: '',
  setId: function(id) {
    if(validUserId(id) {
      this._id = id;
    }
  },
  sayHello: function() {
    alert('Hi! My name is '+ this.name());
  }
});

var usr = new User();
usr.setName('Anders');
// Will alert "Hi! My name is Anders"
usr.sayHello();

So what is does is that it takes all properties of the “class” that begins with an underscore, and generates getters and setters for them, if a getter/setter isn’t already defined. The format for the methods are setProperty() and property(), so if you have a property called “_first_name”, the setter becomes “setFirstName”, and the getter becomes “firstName”.

Happy coding!


About this entry