重构JavaScript / TypeScript:消除重复的代码块

问题描述 投票:-2回答:4

我怎样才能缩短这个怪物块? (非阵列解决方案)

setFooTypeFlag(flag: string) {
  switch (flag) {
    case 'a':
      this.fooType.a = true;  
      this.fooType.b = false;
      this.fooType.c = false;
      this.fooType.d = false;
      break;
    case 'b'
      this.fooType.a = false;
      this.fooType.b = true;
      this.fooType.c = false;
      this.fooType.d = false;
      break;
    case 'c':
      this.fooType.a = false;
      this.fooType.b = false;
      this.fooType.c = true;
      this.fooType.d = false;
      break;
    case 'd':
      this.fooType.a = false;
      this.fooType.b = false;
      this.fooType.c = false;
      this.fooType.d = true;
      break;
  }
}
javascript typescript switch-statement refactoring
4个回答
3
投票

它够短吗? :)

基本上,迭代每个键,只需将所有内容设置为flag === key :)

setFooTypeFlag(flag: string) {
  Object.keys(this.fooType).forEach(key => {
      this.fooType[key] = flag === key;
  });
}

如果在开头,this还没有钥匙,请参考answer of Jack


1
投票

使用动态属性名称。这将适用于任何可能性,并且它不需要您事先初始化它们:

setFooTypeFlag(flag: string) {
  var chars = ["a", "b", "c", "d"];
  for (var i = 0; i < chars.length; i++) {
    this.fooType[chars[i]] = chars[i] == flag;
  }
}

1
投票
enum fooTypes {
  "a" = "a",
  "b" = "b",
  "c" = "c",
  "d" = "d"
}

interface IFooFlags {
  [key: string]: boolean;
}

const defaultFooTypes = new Map<fooTypes, boolean>([
  [fooTypes.a, true],
  [fooTypes.b, true],
  [fooTypes.c, true],
  [fooTypes.d, true]
]);

const fooTypesMappings = new Map<fooTypes, boolean[]>([
  [fooTypes.a, [true, false, false, false]],
  [fooTypes.b, [false, true, false, false]],
  [fooTypes.c, [false, false, true, false]],
  [fooTypes.d, [false, false, false, true]]
]);

class MyClass {
  private mappings = fooTypesMappings;
  private fooTypes = defaultFooTypes;

  private setFooTypes(values: boolean[]): void {
    [...this.fooTypes.keys()].forEach((key, index) =>
      this.fooTypes.set(key, values[index])
    );
  }

  // In modern engines you can return:
  // Object.fromEntries(this.fooTypes)
  public getFooTypes(): IFooFlags {
    return [...this.fooTypes].reduce(
      (obj, { 0: key, 1: val }) => ({ ...obj, [key]: val }),
      {}
    );
  }

  public setFooTypeFlag(flag: fooTypes): void {
    const flagTypes = this.mappings.get(flag);
    if (!flagTypes) {
      throw new Error("Invalid flag type");
    }
    this.setFooTypes(flagTypes);
  }
}

const fooLover = new MyClass();
fooLover.setFooTypeFlag(fooTypes.d);
alert(JSON.stringify(fooLover.getFooTypes()));

Here is a demo of it


1
投票

我也从@ jack-bashford的答案中获得灵感:

class MyClass {
  private flags = [...Array(26)].map((_, i) => (i + 10).toString(36));
  private minObjectKeys = 4;

  public buildBaseObject(flag: string): any {
    return this.getFlagPortion(flag).reduce(
      (obj, key) => ({ ...obj, [key]: key === flag }),
      {}
    );
  }

  private getFlagPortion(flag: string): string[] {
    const sliceEndPositon = this.getSliceEndPosition(flag);
    return this.flags.slice(0, sliceEndPositon);
  }

  private getSliceEndPosition(flag: string): number {
    const flagPosition = this.flags.indexOf(flag) + 1;
    return flagPosition < this.minObjectKeys
      ? this.minObjectKeys
      : flagPosition;
  }
}

const fooLover = new MyClass();
alert(JSON.stringify(fooLover.buildBaseObject("d")));

Here is the demo

© www.soinside.com 2019 - 2024. All rights reserved.