删除 if 语句



我正在为 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 { ...

让我更抽象地表示代码的样子:

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;

在不同条件下存在三次。


首先

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

行为相同(可以简化为(:

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

因为只有当条件A和条件B都为真时,里面的代码才会执行。这是第一步,重复的部分可以缩短为:

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);
}

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

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有一个更好的答案,展示了更好的编程实践,去看看他的解决方案。

最新更新