删除if语句

时间:2019-11-22 21:20:28

标签: javascript node.js discord.js

我正在为Discord做一个机器人。要在用户键入命令时加载命令,我需要验证命令是否存在,但是现在我有三倍几乎相同的if语句。有没有办法只用一个表达式获得所有内容?

    if (!client.commands[cat]) return;

    if (client.commands[cat][command]) {

        if (client.commands[cat][command].conf) {
            if (client.elevationManager.calculateGuildElevation(message.author.id, message.guild) < client.commands[cat][command].conf.elevation) return message.reply(`you don't have the required elevation to use this command.`);
            if (client.commands[cat][command].conf.accountRequired)
                if (!(await client.accountsManager.findById(message.author.id))) return message.reply(`you must have an account to use this command ! Type \`,,account create\` to get one.`);
            return client.commands[cat][command].run(client, args, message);

        } else if (!args[0]) {
            if (client.elevationManager.calculateGuildElevation(message.author.id, message.guild) < client.commands[cat][command].conf.elevation) return message.reply(`you don't have the required elevation to use this command.`);
            if (client.commands[cat][command].conf.accountRequired)
                if (!(await client.accountsManager.findById(message.author.id))) return message.reply(`you must have an account to use this command ! Type \`,,account create\` to get one.`);
            return client.commands[cat][command].run(client, args, message);

        } else if (!client.commands[cat][args[0]]) {
            if (client.elevationManager.calculateGuildElevation(message.author.id, message.guild) < client.commands[cat][command].conf.elevation) return message.reply(`you don't have the required elevation to use this command.`);
            if (client.commands[cat][command].conf.accountRequired)
                if (!(await client.accountsManager.findById(message.author.id))) return message.reply(`you must have an account to use this command ! Type \`,,account create\` to get one.`);
            return client.commands[cat][command].run(client, args, message);

        } else { ...

2 个答案:

答案 0 :(得分:2)

让我更抽象地表示代码是什么样的:

if (mainCondition1) {
  if (subCondition1) return result1;
  if (subCondition2)
    if (subCondition3) return result2;
   return result3;
} else if (mainCondition2) {  
  if (subCondition1) return result1;
  if (subCondition2)
    if (subCondition3) return result2;
   return result3;
} else if (mainCondition3) {
  if (subCondition1) return result1;
  if (subCondition2)
    if (subCondition3) return result2;
   return result3;
}

这使得更容易推理代码。准确地知道重复在哪里,它是

if (subCondition1) return result1;
if (subCondition2)
  if (subCondition3) return result2;
return result3;

在不同的条件下出现3次。


首先

if (A) { 
  if (B) { 
   doSomething() 
  } 
}

具有相同的(并且可以简化为):

if (A && B) { 
 doSomething() 
}

因为条件A和条件B都为true时,内部代码仅执行 。这是第一步,重复的部分可以缩短为:

if (subCondition1) return result1;
if (subCondition2 && subCondition3) return result2;
return result3;

接下来是结构:

if (A) {
  doSomething()
} else if (B) {
  doSomething()
}

也可以表示为简单的布尔代数:

if (A || B) {
  doSomething()
}

因为如果至少一个条件正确,则将执行内部代码。

将此规则放到位,三个重复的部分(在三种不同条件下)折叠为一个块:

if (mainCondition1 || mainCondition2 || mainCondition3) {
  if (subCondition1) return result1;
  if (subCondition2 && subCondition3) return result2;
  return result3;
}

现在,只需提取逻辑,就可以简化完整表达式:

//extract into variables - no evaluation overhead
const mainCondition1 = client.commands[cat][command].conf;
const mainCondition2 = !args[0];
const mainCondition3 = !client.commands[cat][args[0]];

//extract into functions - only evaluate if needed
const subCondition1 = () => client.elevationManager.calculateGuildElevation(message.author.id, message.guild) < client.commands[cat][command].conf.elevation;
const subCondition2 = () => client.commands[cat][command].conf.accountRequired;
const subCondition3 = async () => !(await client.accountsManager.findById(message.author.id));

if (mainCondition1 || mainCondition2 || mainCondition3) {
  if (subCondition1()) 
    return message.reply(`you don't have the required elevation to use this command.`);
  if (subCondition2() && await subCondition3()) 
    return message.reply(`you must have an account to use this command ! Type \`,,account create\` to get one.`);
  return client.commands[cat][command].run(client, args, message);
}

随时将更有意义的名称附加到变量和函数。它们应该真正反映内容的内容,并使您的代码自记录。由于我实际上并不知道它们背后的意图是什么,因此我想以此为例来说明这可能是什么样的:

const hasConfiguration = client.commands[cat][command].conf;
const noArgumentSupplied = !args[0];
const commandDoesNotSupportArgument = !client.commands[cat][args[0]];

const authorHasInsufficientElevation = () => client.elevationManager.calculateGuildElevation(message.author.id, message.guild) < client.commands[cat][command].conf.elevation;
const accountRequiredForCommand = () => client.commands[cat][command].conf.accountRequired;
const accountDoesNotExist = async () => !(await client.accountsManager.findById(message.author.id));

if (hasConfiguration || noArgumentSupplied || commandDoesNotSupportArgument ) {
  if (authorHasInsufficientElevation()) 
    return message.reply(`you don't have the required elevation to use this command.`);
  if (accountRequiredForCommand() && await accountDoesNotExist()) 
    return message.reply(`you must have an account to use this command ! Type \`,,account create\` to get one.`);
  return client.commands[cat][command].run(client, args, message);
}

答案 1 :(得分:0)

只需使用||(或)运算符

    if (!client.commands[cat]) return;

    if (client.commands[cat][command]) {

        if (client.commands[cat][command].conf || !args[0] || !client.commands[cat][args[0]]) {
            if (client.elevationManager.calculateGuildElevation(message.author.id, message.guild) < client.commands[cat][command].conf.elevation) return message.reply(`you don't have the required elevation to use this command.`);
            if (client.commands[cat][command].conf.accountRequired)
                if (!(await client.accountsManager.findById(message.author.id))) return message.reply(`you must have an account to use this command ! Type \`,,account create\` to get one.`);
            return client.commands[cat][command].run(client, args, message);

        } else { ...

@VLAZ对此有更好的回答,可以显示更好的编程实践,请查看他的解决方案。