shake, with fries

by Zach Carter

Posts tagged jscript

May31

A Naive, JScript Compatible Getter Pattern

javascript programming jscript | comments

Modern JavaScript implementations let you define getters and setters for properties of objects. The new syntax involved will, of course, make your code incompatible with less capable JavaScript VMs if you chose to use it, but the behavior of the rest of your code will also be different, even when syntactically identical. This little experiment of mine was aimed to address the latter issue (well, at least for getters.)

The following is a naive implementation of getters that would be somewhat compatible with language supported getters in common usage (setters are just not possible!) Perhaps this technique could prove useful in some contexts but the reliance on type coercion makes it dubious...

Take, for example, the behavior of a rectangle:

var rect = new Rectangle(4,5);

rect.area; // returns 20

rect.width = 6;

rect.area; // returns 30

The area property updates dynamically, by way of a getter. With proper getters, you could implement the Rectangle class like so:

function Rectangle(width, height){
  this.width = width;
  this.height = height;

  this.__defineGetter__('area', function (){
    return this.width * this.height;
  });
}

Now let's see the naive, JScript compatible approach:

function Rectangle(width, height){
  this.width = width;
  this.height = height;

  var that = this;

  var area = function(){};
  area.valueOf = function(){
    return that.width * that.height;
  };

  this.area = area;
}

The key idea here is that area is a complex value that will be coerced into a primitive by most operations, calling its valueOf method. Let's see how well it works:

var rect = new Rectangle(4,5);

assert(typeof rect.area === 'function'); // it's really a function
assert(typeof +rect.area === 'number');  // but can be coerced into a number

assert(rect.area == 20);                 // type coercion
assert(rect.area !== 20);                // === and !== don't coerce type
assert(rect.area + 5 == 25);             // operator type coercion
assert(rect.area + 5 === 25);            // coercion happens before equality comparison

rect.width = 6;
assert(rect.area == 30);                 // area updates as expected

This is definitely a stretch of the intentions of the language, and as I mentioned, very dubious. But, if you could get away with it you would be able to utilize getter behavior on lesser JavaScript VMs without changing your API. Neat.

Edit: use valueOf, not toString. DUH