Avoiding inconsistent unit values

As in the examples above, we certainly could allow string literals to be passed into the constructor. But, what happens when we use inches in one case, Inches in another case, and inch in yet another case? There are too many possible conditions to account for when testing against the units value. A simple solution to this is to provide a basic "units map":

So, our new method of creating a Number object would look something like:

x = new Number(30, Number.units.inches);

But, what would prevent supplying string literals to the constructor? You could also perform some validation in the constructor:

Number = function(num, unit) {
  this.value = num;

  var unitValidates = false;

  for each(value in Number.units) {
    if(value === unit) {
      unitValidates = true;
      break;
    }
  }

  // an assertion would make more sense here
  // unless we're accepting unit input from the user
  if(!unitValidates) {
    throw new Error(unit + ' unit is not allowed');
    return false;
  }

  this.unit = unit;
};

 

Dropping in the conversion functions

Next comes the need to convert between units. There are two ways we can do this:

Number.unitMap = [
{Number.units.inches :
  {Number.unit.millimeters: 25.4,
   Number.unit.feet: 1 / 12 },
{Number.units.millimeters:

  {Number.unit.inches: 1 / 25.4,
   Number.unit.feet: 1 / (25.4 * 12) },
{Number.units.feet:
  {Number.unit.inches: 12,
   Number.unit.millimeters: 12 * 25.4 }
]

  1. Modify the Number object itself
    Number.prototype.changeUnit = function(unit) {

      this.value = this.value * Number.unitMap[this.getUnit][unit];
    }
     
  2. Use a function to return the converted value

    Number.prototype.convertUnit = function(unit) {
      return this.value * Number.unitMap[this.getUnit][unit];
    }

 

Tags:

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *