有没有办法让一个对象有一个 switch 语句,用例验证一个键是否存在? - javascript

Is there a way to have a switch statement for an object with cases that validate if a key is present? - javascript

我的目标: 将 if 语句链转换为 switch 语句,并使其在 case 中瀑布式下降
我正在使用的内容: 解码的 Minecraft NBT 数据(基本上只是一个对象)
我的问题是:我不确定 switch 语句是否可以检测对象中是否存在键,除非我做大量的 switch 语句,但那样的话它会是如果我使用一连串的 if 语句会更容易。
对象的示例如下所示:

nbt = {
  type: 'compound',
  name: '',
  value: {
    i: {
      type: 'list',
      value: {
        type: 'compound',
        value: [
          {
            id: { type: 'short', value: 276 },
            Count: { type: 'byte', value: 1 },
            tag: {
              type: 'compound',
              value: {
                Unbreakable: { type: 'byte', value: 1 },
                HideFlags: { type: 'int', value: 254 },
                display: {
                  type: 'compound',
                  value: {
                    Lore: {
                      type: 'list',
                      value: {
                        type: 'string',
                        value: [
                          '§7Damage: §c+35',
                          '',
                          '§7§8This item can be reforged!',
                          '§a§lUNCOMMON SWORD'
                        ]
                      }
                    },
                    Name: { type: 'string', value: '§aDiamond Sword' }
                  }
                },
                ExtraAttributes: {
                  type: 'compound',
                  value: {
                    originTag: { type: 'string', value: 'CRAFTING_GRID_SHIFT' },
                    id: { type: 'string', value: 'DIAMOND_SWORD' },
                    uuid: {
                      type: 'string',
                      value: '3aa2d326-541f-4a2e-abae-04366b4771d3'
                    },
                    timestamp: { type: 'string', value: '6/1/21 8:44 PM' }
                  }
                }
              }
            },
            Damage: { type: 'short', value: 0 }
          }
        ]
      }
    }
  }
}

之后我删除了一些不需要的键,我得到了这样的结果:

{
  name: '§aDiamond Sword',
  lore: [
    '§7Damage: §c+35',
    '',
    '§7§8This item can be reforged!',
    '§a§lUNCOMMON SWORD'
  ],
  attributes: {
    rarity_upgrades: undefined,
    modifier: undefined,
    dungeon_item_level: undefined,
    dungeon_master_level: 0,
    hot_potato_count: undefined,
    fuming_potato_count: 0,
    art_of_war_count: undefined,
    enchantments: undefined,
    runes: undefined,
    ability_scroll: undefined,
    id: 'DIAMOND_SWORD'
  }
}

(每个物品都有不同的修饰符,有些有符文,有些没有,有些物品有特殊物品,如能力卷轴,但是这个物品完全干净,上面什么也没有,这就是为什么你看到 undefined 对于很多字段。如果一个项目没有,比如说,能力卷轴,它就不会出现在 NBT 对象中。)
我设想的 case 语句看起来像这样:

switch (item_schema) {
  case item_schema.attributes.fuming_potato_count > 10:
    console.log('Detected Fuming HPBs')
  case item_schema.attributes.dungeon_item_level > 5:
    console.log('Detected Master Stars')
  case typeof item_schema.attributes.ability_scroll !== 'undefined':
    console.log('Detected Necron\'s Blade Ability Scrolls')
  case typeof item_schema.attributes.enchantments !== 'undefined':
    console.log('Detected Enchantments')
  default:
    console.log('No Modifiers Detected')
}

这甚至可以做到吗?我只是想清理我的代码,在此之前我只有一个 if 语句链,但我觉得这可能是一种更简单、更清晰的方法。提前致谢:)

一种选择是使用 shorthand 标识符

将您的测试合并到一个对象中
const cond = [
{'Detected Fuming HPBs': item_schema.attributes.fuming_potato_count > 10,
'Detected Master Stars': item_schema.attributes.dungeon_item_level > 5
}

..等等。然后你可以在你需要的地方测试它们或者循环输出

let x = 3,
  y = 4
const cond = [
{'X is 4': x === 4},
{'X is less than 20': x < 20},
{'Y is 4': y === 4}
];

cond.forEach(obj => {
  const [output, condition] = Object.entries(obj)[0];
  console.log(output, "? :: ", condition)
});


使用switch

您总是希望 运行 切换,因此将其设置为始终使用 true 进行处理,但结果可能不是您所期望的:

The optional break statement associated with each case label ensures that the program breaks out of switch once the matched statement is executed and continues execution at the statement following switch. If break is omitted, the program continues execution at the next statement in the switch statement. The break statement is not required if a return statement precedes it.

let hasCondition = false
switch (true) {
  case item_schema.attributes.fuming_potato_count > 10:
    console.log('Detected Fuming HPBs');
    hasCondition = true;
  case item_schema.attributes.dungeon_item_level > 5:
    console.log('Detected Master Stars')
    hasCondition = true;
  //case typeof item_schema.attributes.ability_scroll !== 'undefined':
  case item_schema.attributes.hasOwnProperty("ability_scroll"):
    console.log('Detected Necron\'s Blade Ability Scrolls')
    hasCondition = true;
  //case item_schema.attributes.enchantments !== 'undefined':
  case item_schema.attributes.hasOwnProperty("enchantments"):
    console.log('Detected Enchantments')
    hasCondition = true;
}

如果您不想在每个 case: 之后放置 break; 语句,您将需要在别处处理 default 条件,因为它总是 运行。

if (!hasCondition) console.log('No Modifiers Detected')

取自:https://dev.to/jasterix/using-a-switch-statement-with-logical-operators-17ni

你可以使用 if 语句做这样的事情:

const item_schema = {
  name: '§aDiamond Sword',
  lore: [
    '§7Damage: §c+35',
    '',
    '§7§8This item can be reforged!',
    '§a§lUNCOMMON SWORD'
  ],
  attributes: {
    rarity_upgrades: undefined,
    modifier: undefined,
    dungeon_item_level: undefined,
    dungeon_master_level: 0,
    hot_potato_count: undefined,
    fuming_potato_count: 0,
    art_of_war_count: undefined,
    enchantments: undefined,
    runes: undefined,
    ability_scroll: undefined,
    id: 'DIAMOND_SWORD'
  }
}

const modifiers = [];

if (item_schema.attributes.fuming_potato_count > 10)
  modifiers.push('Detected Fuming HPBs')
if (item_schema.attributes.dungeon_item_level > 5)
  modifiers.push('Detected Master Stars')
if (typeof item_schema.attributes.ability_scroll !== 'undefined')
  modifiers.push('Detected Necron\'s Blade Ability Scrolls')
if (typeof item_schema.attributes.enchantments !== 'undefined')
  modifiers.push('Detected Enchantments')

if (modifiers.length)
  console.log(...modifiers)
else
  console.log('No Modifiers Detected')

如果你有很多这些,你可以查看一个库来帮助你验证模式:for example Yup.