Skip to content

在JavaScript中创建一个单位转换器数据结构

基于类的单位转换器数据结构

在最简单的形式中,任何基于单位的值都是一个带有附加单位的数值。只要单位是兼容的并且你知道它们之间的转换因子,就可以很容易地从一个单位转换到另一个单位。

应用这个逻辑,我们可以为距离单位创建一个简单的数据结构类。该数据结构将在内部将值存储为厘米,并提供从其他单位转换的方法。

为了避免手动添加每个转换,我们可以使用Object.defineProperty()轻松地为每个单位创建一个getter,它将计算指定单位的值。类似地,我们还可以为每个单位创建一个静态方法,该方法将创建一个新的数据结构实例,并将值转换为内部存储的单位。

class Distance {
  static conversions = {
    inches: 2.54,
    feet: 30.48,
    yards: 91.44,
    miles: 160934.4,
    centimeters: 1,
    meters: 100,
    kilometers: 100000,
  };

  constructor(cm) {
    this.cm = cm;
  }
}

Object.entries(Distance.conversions).forEach(([unit, conversion]) => {
  Object.defineProperty(
    Distance,
    `from${unit.charAt(0).toUpperCase() + unit.slice(1)}`,
    {
      get: function () {
        return value => new Distance(value * conversion);
      },
    }
  );

  Object.defineProperty(Distance.prototype, unit, {
    get: function () {
      return this.cm / conversion;
    },
  });
});

const distance = Distance.fromMeters(10);

单位转换器数据结构工厂函数

虽然这对于特定类型的测量工作得很好,但我们必须为不同类型的测量重复整个过程。这并不理想,因为我们可能会出现很多代码重复

幸运的是,JavaScript使用原型继承,这意味着我们可以使用一个函数来代替类,并应用相同类型的逻辑来创建一个通用的单位转换器数据结构。这将允许我们创建一个单一的工厂函数,用于创建任何类型的测量单位转换器。

const createUnitConverter = unitCoversions => {
  // 创建一个充当数据结构的函数
  const UnitConverter = function (unit) {
    this.unit = unit;
  };

  // 添加静态方法
  Object.entries(unitCoversions).forEach(([unit, conversion]) => {
    Object.defineProperty(
      UnitConverter,
      `from${unit.charAt(0).toUpperCase() + unit.slice(1)}`,
      {
        get: function () {
          return value => new UnitConverter(value * conversion);
        },
      }
    );

    // 添加实例方法
    Object.defineProperty(UnitConverter.prototype, unit, {
      get: function () {
        return this.unit / conversion;
      },
    });
  });

  return UnitConverter;
};

const Data = createUnitConverter({
  bits: 1,
  bytes: 8,
  kilobits: 1000,
  kilobytes: 8000,
  megabits: 1000000,
  megabytes: 8000000,
  gigabits: 1000000000,
  gigabytes: 8000000000,
  terabits: 1000000000000,
  terabytes: 8000000000000,
  petabits: 1000000000000000,
  petabytes: 8000000000000000,
});

const data = Data.fromBytes(2000);

```javascript
data.kilobytes; // 2
data.bits; // 16000

虽然这对于简单的公式有效,但像温度转换这样的东西就要复杂一些。我不会在这里详细介绍,但我相信你可以很容易地找出必要的调整,以允许使用函数而不是简单的转换因子