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":
Number.units = { inches: 'in', millimeters: 'mi', feet: 'ft' }
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 }
]
- Modify the Number object itself
Number.prototype.changeUnit = function(unit) {
this.value = this.value * Number.unitMap[this.getUnit][unit];
}
- Use a function to return the converted value
Number.prototype.convertUnit = function(unit) {
return this.value * Number.unitMap[this.getUnit][unit];
}
1 Comment