A plea to IE

Please, please implement getters and setters in your JavaScript engine. I cannot tell you how much I want to add this to JS.Class:

var MagicMethods = {
  included: function(klass) {

    var define = function(object, name) {
      var shortName = name.replace(/^[gs]et[A-Z]/,
          function(s) { return s.charAt(3).toLowerCase() });

      if (/^get[A-Z]/.test(name))
        object.__defineGetter__(shortName,
          function() { return this[name]() });

      if (/^set[A-Z]/.test(name))
        object.__defineSetter__(shortName,
          function(value) { return this[name](value) });
    };

    for (var key in klass.prototype)
      define(klass.prototype, key);

    if (klass.instanceMethod)
      klass.instanceMethod = (function(wrapped) {
        return function() {
          var name = arguments[0];
          define(klass.prototype, name);
          return wrapped.apply(klass, arguments);
        };
      })(klass.instanceMethod);
  }
};

This mixin needs a few type checks adding but I didn’t want to obscure the main idea. When mixed into a class, MagicMethods will intercept all instance method definitions and, if the method name looks like getX or setX it will add a shorthand getter or setter to the class. So, for example, the main collection class in Ojay has a bunch of methods like setStyle, getRegion and what-not. If we use the above mixin, we can get more intuitive code:

Ojay.DomCollection.include(MagicMethods);

// Set style of all paras
$('p').setStyle({fontStyle: 'italic'});    // old
$('p').style = {fontStyle: 'italic'};      // new

// Find region of the title
var region = $('h1').getRegion();    // old
var region = $('h1').region;         // new

Granted, I’m not saving a huge amount of typing here, but getters and setters get you out of the trap of having to make everything a method rather than a property to enforce encapsulation. style= and region in the above code look like property accesses, but are really function calls to setStyle() and getRegion() under the covers. You can implement something as a property to begin with, then later on you can change it to a getter method without breaking anyone’s code. It really comes into its own when using MethodChain:

MagicMethods.included(JS.MethodChain);

$('p').on('mouseover').style = {color: 'red'};
$('a').on('click', $.stopDefault).content = 'Clicked!'

This makes for a more declarative style for doing simpe event handling.

Anyways, this is all a moot point because this technique only works in Firefox and Safari. If we’re going to count beta versions, Opera 9.5 supports it too (thanks to John Resig for the heads-up). I’ve no idea whether IE8 plans to support it, and I don’t think it’s in the ECMAScript standard (3 or 4) so they’ve really no obligation to (comments proving me wrong greatly appreciated). In any case, the need to support IE 6 and 7 for the foreseeable future means I can’t use this feature, and I’m pretty sure there’s no way to reliably fake it in IE. Any ideas on 3-by-5 cards, please.

If you’ve enjoyed this article, you might enjoy my recently published book JavaScript Testing Recipes. It’s full of simple techniques for writing modular, maintainable JavaScript apps in the browser and on the server.