如何重构 switch case 以从 class 调用方法?

How can I refactor the switch case to call methods from a class?

我有一个扩展玩家 class 的英雄 class,这个英雄可以执行各种动作,这些动作中的大部分都被玩家 class 覆盖了,到目前为止还不错.

class Hero extends Player {
  constructor(level = 1) {
    super();
    this.level = level;
  }

  // override
  attack() {
    return 'attacking';
  }

  defend() {
    return 'defending';
  }

  walk() {
    return 'walking';
  }

  run() {
    return 'running';
  }

  fly() {
    return 'flying';
  }

  jump() {
    return 'jumping';
  }
}

module.exports = Hero

现在我需要通过发送参数来动态调用这些动作,例如,我在数据库中查找用户并检查动作的类型是什么(整数),如果是0,则执行attack()方法,如果为1,则执行defend()方法。我创建了一个包含所有可能情况的 switch case,但是每当我添加一个新动作时,我都必须修改 switch,它会变得越来越大。如何最好地使用它?知道我必须使用“类型”参数动态调用这些方法。

const hero = new Hero();
let type = 1; // this type is dynamic and comes from a database API
let result = null;
switch (type) {
    case 0:
        result = hero.attack();
        break;

    case 1:
        result = hero.defend();
        break;

    case 2:
        result = hero.walk();
        break;

    case 3:
        result = hero.run();
        break;

    case 4:
        result = hero.fly();
        break;

    case 5:
        result = hero.jump();
        break;
}

console.log(result)

您可以使用对象将数字映射到函数,这将使它变得更小(每行一行)。这是一个简化的例子:

let actions = {
    1: attack,
    2: defend,
};

actions[type]();

而不是将函数命名为 attackfly。您可以将该函数命名为 type 您期望从数据库中获得的名称。在现有的背景下 它是整数,所以我使用整数来实现。

class Hero {
  constructor(level = 1) {
    this.level = level;
  }

  1() {
    return 'attacking';
  }

  2() {
    return 'defending';
  }

  3() {
    return 'walking';
  }

  4() {
    return 'running';
  }

  5() {
    return 'flying';
  }

  jumping() {
    return 'jumping';
  }
}

const hero = new Hero();
let type = 1; // this type is dynamic and comes from a database API
let result = eval('hero[' + type + ']()');

console.log(result)

type = 'jumping' // this type is dynamic and comes from a database API
result = eval('hero.' + type + '()');

console.log(result)

let result = eval('hero[' + type + ']()'); 并且我生成了函数名称并动态评估了它的值。这些资源可能会对您有所帮助 double dispatch and dynamic-function-names

如果您的操作类型确实定义为从 0 开始的连续整数,那么您可以只使用数组而不是映射;

var actions = [attack, defend, walk, ...],
    type    = 0;
actions[type](); // "attacking"